Home | History | Annotate | Download | only in gpu
      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