1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "GrLayerCache.h" 9#include "GrLayerHoister.h" 10#include "GrRecordReplaceDraw.h" 11 12#include "SkCanvas.h" 13#include "SkDeviceImageFilterProxy.h" 14#include "SkDeviceProperties.h" 15#include "SkGpuDevice.h" 16#include "SkGrPixelRef.h" 17#include "SkLayerInfo.h" 18#include "SkRecordDraw.h" 19#include "SkSurface.h" 20#include "SkSurface_Gpu.h" 21 22// Create the layer information for the hoisted layer and secure the 23// required texture/render target resources. 24static void prepare_for_hoisting(GrLayerCache* layerCache, 25 const SkPicture* topLevelPicture, 26 const SkMatrix& initialMat, 27 const SkLayerInfo::BlockInfo& info, 28 const SkIRect& srcIR, 29 const SkIRect& dstIR, 30 SkTDArray<GrHoistedLayer>* needRendering, 31 SkTDArray<GrHoistedLayer>* recycled, 32 bool attemptToAtlas, 33 int numSamples) { 34 const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; 35 36 GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->uniqueID(), 37 SkToInt(info.fSaveLayerOpID), 38 SkToInt(info.fRestoreOpID), 39 srcIR, 40 dstIR, 41 initialMat, 42 info.fKey, 43 info.fKeySize, 44 info.fPaint); 45 GrSurfaceDesc desc; 46 desc.fFlags = kRenderTarget_GrSurfaceFlag; 47 desc.fWidth = srcIR.width(); 48 desc.fHeight = srcIR.height(); 49 desc.fConfig = kSkia8888_GrPixelConfig; 50 desc.fSampleCnt = numSamples; 51 52 bool locked, needsRendering; 53 if (attemptToAtlas) { 54 locked = layerCache->tryToAtlas(layer, desc, &needsRendering); 55 } else { 56 locked = layerCache->lock(layer, desc, &needsRendering); 57 } 58 if (!locked) { 59 // GPU resources could not be secured for the hoisting of this layer 60 return; 61 } 62 63 if (attemptToAtlas) { 64 SkASSERT(layer->isAtlased()); 65 } 66 67 GrHoistedLayer* hl; 68 69 if (needsRendering) { 70 if (!attemptToAtlas) { 71 SkASSERT(!layer->isAtlased()); 72 } 73 hl = needRendering->append(); 74 } else { 75 hl = recycled->append(); 76 } 77 78 layerCache->addUse(layer); 79 hl->fLayer = layer; 80 hl->fPicture = pict; 81 hl->fLocalMat = info.fLocalMat; 82 hl->fInitialMat = initialMat; 83 hl->fPreMat = initialMat; 84 hl->fPreMat.preConcat(info.fPreMat); 85} 86 87// Compute the source rect and return false if it is empty. 88static bool compute_source_rect(const SkLayerInfo::BlockInfo& info, const SkMatrix& initialMat, 89 const SkIRect& dstIR, SkIRect* srcIR) { 90 SkIRect clipBounds = dstIR; 91 92 SkMatrix totMat = initialMat; 93 totMat.preConcat(info.fPreMat); 94 totMat.preConcat(info.fLocalMat); 95 96 if (info.fPaint && info.fPaint->getImageFilter()) { 97 info.fPaint->getImageFilter()->filterBounds(clipBounds, totMat, &clipBounds); 98 } 99 100 if (!info.fSrcBounds.isEmpty()) { 101 SkRect r; 102 103 totMat.mapRect(&r, info.fSrcBounds); 104 r.roundOut(srcIR); 105 106 if (!srcIR->intersect(clipBounds)) { 107 return false; 108 } 109 } else { 110 *srcIR = clipBounds; 111 } 112 113 return true; 114} 115 116// Atlased layers must be small enough to fit in the atlas, not have a 117// paint with an image filter and be neither nested nor nesting. 118// TODO: allow leaf nested layers to appear in the atlas. 119void GrLayerHoister::FindLayersToAtlas(GrContext* context, 120 const SkPicture* topLevelPicture, 121 const SkMatrix& initialMat, 122 const SkRect& query, 123 SkTDArray<GrHoistedLayer>* atlased, 124 SkTDArray<GrHoistedLayer>* recycled, 125 int numSamples) { 126 if (0 != numSamples) { 127 // MSAA layers are currently never atlased 128 return; 129 } 130 131 GrLayerCache* layerCache = context->getLayerCache(); 132 133 layerCache->processDeletedPictures(); 134 135 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); 136 137 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); 138 if (!topLevelData) { 139 return; 140 } 141 142 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData); 143 if (0 == topLevelGPUData->numBlocks()) { 144 return; 145 } 146 147 atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks()); 148 149 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) { 150 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i); 151 152 // TODO: ignore perspective projected layers here? 153 bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested || 154 (info.fPaint && info.fPaint->getImageFilter()); 155 156 if (disallowAtlasing) { 157 continue; 158 } 159 160 SkRect layerRect; 161 initialMat.mapRect(&layerRect, info.fBounds); 162 if (!layerRect.intersect(query)) { 163 continue; 164 } 165 166 const SkIRect dstIR = layerRect.roundOut(); 167 168 SkIRect srcIR; 169 170 if (!compute_source_rect(info, initialMat, dstIR, &srcIR) || 171 !GrLayerCache::PlausiblyAtlasable(srcIR.width(), srcIR.height())) { 172 continue; 173 } 174 175 prepare_for_hoisting(layerCache, topLevelPicture, initialMat, 176 info, srcIR, dstIR, atlased, recycled, true, 0); 177 } 178 179} 180 181void GrLayerHoister::FindLayersToHoist(GrContext* context, 182 const SkPicture* topLevelPicture, 183 const SkMatrix& initialMat, 184 const SkRect& query, 185 SkTDArray<GrHoistedLayer>* needRendering, 186 SkTDArray<GrHoistedLayer>* recycled, 187 int numSamples) { 188 GrLayerCache* layerCache = context->getLayerCache(); 189 190 layerCache->processDeletedPictures(); 191 192 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); 193 194 const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); 195 if (!topLevelData) { 196 return; 197 } 198 199 const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData); 200 if (0 == topLevelGPUData->numBlocks()) { 201 return; 202 } 203 204 // Find and prepare for hoisting all the layers that intersect the query rect 205 for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) { 206 const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i); 207 if (info.fIsNested) { 208 // Parent layers are currently hoisted while nested layers are not. 209 continue; 210 } 211 212 SkRect layerRect; 213 initialMat.mapRect(&layerRect, info.fBounds); 214 if (!layerRect.intersect(query)) { 215 continue; 216 } 217 218 const SkIRect dstIR = layerRect.roundOut(); 219 220 SkIRect srcIR; 221 if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) { 222 continue; 223 } 224 225 prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, srcIR, dstIR, 226 needRendering, recycled, false, numSamples); 227 } 228} 229 230void GrLayerHoister::DrawLayersToAtlas(GrContext* context, 231 const SkTDArray<GrHoistedLayer>& atlased) { 232 if (atlased.count() > 0) { 233 // All the atlased layers are rendered into the same GrTexture 234 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); 235 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( 236 atlased[0].fLayer->texture()->asRenderTarget(), &props)); 237 238 SkCanvas* atlasCanvas = surface->getCanvas(); 239 240 for (int i = 0; i < atlased.count(); ++i) { 241 const GrCachedLayer* layer = atlased[i].fLayer; 242 const SkPicture* pict = atlased[i].fPicture; 243 const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop); 244 SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) 245 246 SkASSERT(!layerPaint || !layerPaint->getImageFilter()); 247 SkASSERT(!layer->filter()); 248 249 atlasCanvas->save(); 250 251 // Add a rect clip to make sure the rendering doesn't 252 // extend beyond the boundaries of the atlased sub-rect 253 const SkRect bound = SkRect::Make(layer->rect()); 254 atlasCanvas->clipRect(bound); 255 atlasCanvas->clear(0); 256 257 // '-offset' maps the layer's top/left to the origin. 258 // Since this layer is atlased, the top/left corner needs 259 // to be offset to the correct location in the backing texture. 260 SkMatrix initialCTM; 261 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY)); 262 initialCTM.preTranslate(bound.fLeft, bound.fTop); 263 initialCTM.preConcat(atlased[i].fPreMat); 264 265 atlasCanvas->setMatrix(initialCTM); 266 atlasCanvas->concat(atlased[i].fLocalMat); 267 268 SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, 269 pict->drawablePicts(), pict->drawableCount(), 270 layer->start() + 1, layer->stop(), initialCTM); 271 272 atlasCanvas->restore(); 273 } 274 275 atlasCanvas->flush(); 276 } 277} 278 279SkBitmap wrap_texture(GrTexture* texture) { 280 SkASSERT(texture); 281 282 SkBitmap result; 283 result.setInfo(texture->surfacePriv().info()); 284 result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref(); 285 return result; 286} 287 288void GrLayerHoister::FilterLayer(GrContext* context, 289 SkGpuDevice* device, 290 const GrHoistedLayer& info) { 291 GrCachedLayer* layer = info.fLayer; 292 293 SkASSERT(layer->filter()); 294 295 static const int kDefaultCacheSize = 32 * 1024 * 1024; 296 297 SkBitmap filteredBitmap; 298 SkIPoint offset = SkIPoint::Make(0, 0); 299 300 const SkIPoint filterOffset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop); 301 302 SkMatrix totMat = SkMatrix::I(); 303 totMat.preConcat(info.fPreMat); 304 totMat.preConcat(info.fLocalMat); 305 totMat.postTranslate(-SkIntToScalar(filterOffset.fX), -SkIntToScalar(filterOffset.fY)); 306 307 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); 308 SkIRect clipBounds = layer->rect(); 309 310 // This cache is transient, and is freed (along with all its contained 311 // textures) when it goes out of scope. 312 SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kDefaultCacheSize)); 313 SkImageFilter::Context filterContext(totMat, clipBounds, cache); 314 315 SkDeviceImageFilterProxy proxy(device, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); 316 const SkBitmap src = wrap_texture(layer->texture()); 317 318 if (!layer->filter()->filterImage(&proxy, src, filterContext, &filteredBitmap, &offset)) { 319 // Filtering failed. Press on with the unfiltered version. 320 return; 321 } 322 323 SkIRect newRect = SkIRect::MakeWH(filteredBitmap.width(), filteredBitmap.height()); 324 layer->setTexture(filteredBitmap.getTexture(), newRect); 325 layer->setOffset(offset); 326} 327 328void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) { 329 for (int i = 0; i < layers.count(); ++i) { 330 GrCachedLayer* layer = layers[i].fLayer; 331 const SkPicture* pict = layers[i].fPicture; 332 const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop); 333 334 // Each non-atlased layer has its own GrTexture 335 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); 336 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( 337 layer->texture()->asRenderTarget(), &props)); 338 339 SkCanvas* layerCanvas = surface->getCanvas(); 340 341 SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); 342 343 // Add a rect clip to make sure the rendering doesn't 344 // extend beyond the boundaries of the layer 345 const SkRect bound = SkRect::Make(layer->rect()); 346 layerCanvas->clipRect(bound); 347 layerCanvas->clear(SK_ColorTRANSPARENT); 348 349 SkMatrix initialCTM; 350 initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY)); 351 initialCTM.preConcat(layers[i].fPreMat); 352 353 layerCanvas->setMatrix(initialCTM); 354 layerCanvas->concat(layers[i].fLocalMat); 355 356 SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, 357 pict->drawablePicts(), pict->drawableCount(), 358 layer->start()+1, layer->stop(), initialCTM); 359 360 layerCanvas->flush(); 361 362 if (layer->filter()) { 363 SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(surface.get()); 364 365 FilterLayer(context, gpuSurf->getDevice(), layers[i]); 366 } 367 } 368} 369 370void GrLayerHoister::UnlockLayers(GrContext* context, 371 const SkTDArray<GrHoistedLayer>& layers) { 372 GrLayerCache* layerCache = context->getLayerCache(); 373 374 for (int i = 0; i < layers.count(); ++i) { 375 layerCache->removeUse(layers[i].fLayer); 376 } 377 378 SkDEBUGCODE(layerCache->validate();) 379} 380 381void GrLayerHoister::PurgeCache(GrContext* context) { 382#if !GR_CACHE_HOISTED_LAYERS 383 GrLayerCache* layerCache = context->getLayerCache(); 384 385 // This code completely clears out the atlas. It is required when 386 // caching is disabled so the atlas doesn't fill up and force more 387 // free floating layers 388 layerCache->purgeAll(); 389#endif 390} 391