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 "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.
     24 static 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.
     88 static 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.
    119 void 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 
    181 void 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 
    230 void 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 
    279 SkBitmap 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 
    288 void 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 
    328 void 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 
    370 void 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 
    381 void 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