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