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 "SkCanvas.h"
     11 #include "SkRecordDraw.h"
     12 #include "GrRecordReplaceDraw.h"
     13 #include "SkGrPixelRef.h"
     14 #include "SkSurface.h"
     15 
     16 // Return true if any layers are suitable for hoisting
     17 bool GrLayerHoister::FindLayersToHoist(const SkPicture* topLevelPicture,
     18                                        const SkRect& query,
     19                                        SkTDArray<HoistedLayer>* atlased,
     20                                        SkTDArray<HoistedLayer>* nonAtlased,
     21                                        GrLayerCache* layerCache) {
     22     bool anyHoisted = false;
     23 
     24     SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
     25 
     26     const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
     27     if (NULL == topLevelData) {
     28         return false;
     29     }
     30 
     31     const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData);
     32     if (0 == topLevelGPUData->numSaveLayers()) {
     33         return false;
     34     }
     35 
     36     // Layer hoisting pre-renders the entire layer since it will be cached and potentially
     37     // reused with different clips (e.g., in different tiles). Because of this the
     38     // clip will not be limiting the size of the pre-rendered layer. kSaveLayerMaxSize
     39     // is used to limit which clips are pre-rendered.
     40     static const int kSaveLayerMaxSize = 256;
     41 
     42     SkAutoTArray<bool> pullForward(topLevelGPUData->numSaveLayers());
     43 
     44     // Pre-render all the layers that intersect the query rect
     45     for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) {
     46         pullForward[i] = false;
     47 
     48         const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i);
     49 
     50         SkRect layerRect = SkRect::MakeXYWH(SkIntToScalar(info.fOffset.fX),
     51                                             SkIntToScalar(info.fOffset.fY),
     52                                             SkIntToScalar(info.fSize.fWidth),
     53                                             SkIntToScalar(info.fSize.fHeight));
     54 
     55         if (!SkRect::Intersects(query, layerRect)) {
     56             continue;
     57         }
     58 
     59         // TODO: once this code is more stable unsuitable layers can
     60         // just be omitted during the optimization stage
     61         if (!info.fValid ||
     62             kSaveLayerMaxSize < info.fSize.fWidth ||
     63             kSaveLayerMaxSize < info.fSize.fHeight ||
     64             info.fIsNested) {
     65             continue;
     66         }
     67 
     68         pullForward[i] = true;
     69         anyHoisted = true;
     70     }
     71 
     72     if (!anyHoisted) {
     73         return false;
     74     }
     75 
     76     atlased->setReserve(atlased->reserved() + topLevelGPUData->numSaveLayers());
     77 
     78     // Generate the layer and/or ensure it is locked
     79     for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) {
     80         if (pullForward[i]) {
     81             const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i);
     82             const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture;
     83 
     84             GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(),
     85                                                                  info.fSaveLayerOpID,
     86                                                                  info.fRestoreOpID,
     87                                                                  info.fOffset,
     88                                                                  info.fOriginXform,
     89                                                                  info.fPaint);
     90 
     91             GrTextureDesc desc;
     92             desc.fFlags = kRenderTarget_GrTextureFlagBit;
     93             desc.fWidth = info.fSize.fWidth;
     94             desc.fHeight = info.fSize.fHeight;
     95             desc.fConfig = kSkia8888_GrPixelConfig;
     96             // TODO: need to deal with sample count
     97 
     98             bool needsRendering = layerCache->lock(layer, desc,
     99                                                    info.fHasNestedLayers || info.fIsNested);
    100             if (NULL == layer->texture()) {
    101                 continue;
    102             }
    103 
    104             if (needsRendering) {
    105                 HoistedLayer* info;
    106 
    107                 if (layer->isAtlased()) {
    108                     info = atlased->append();
    109                 } else {
    110                     info = nonAtlased->append();
    111                 }
    112 
    113                 info->fLayer = layer;
    114                 info->fPicture = pict;
    115             }
    116         }
    117     }
    118 
    119     return anyHoisted;
    120 }
    121 
    122 static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
    123     SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
    124     result->setInfo(info);
    125     result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
    126 }
    127 
    128 static void convert_layers_to_replacements(const SkTDArray<GrLayerHoister::HoistedLayer>& layers,
    129                                            GrReplacements* replacements) {
    130     // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer?
    131     for (int i = 0; i < layers.count(); ++i) {
    132         GrReplacements::ReplacementInfo* layerInfo = replacements->push();
    133         layerInfo->fStart = layers[i].fLayer->start();
    134         layerInfo->fStop = layers[i].fLayer->stop();
    135         layerInfo->fPos = layers[i].fLayer->offset();;
    136 
    137         SkBitmap bm;
    138         wrap_texture(layers[i].fLayer->texture(),
    139                      !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().width()
    140                                                     : layers[i].fLayer->texture()->width(),
    141                      !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().height()
    142                                                     : layers[i].fLayer->texture()->height(),
    143                      &bm);
    144         layerInfo->fImage = SkImage::NewTexture(bm);
    145 
    146         layerInfo->fPaint = layers[i].fLayer->paint()
    147                                 ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint()))
    148                                 : NULL;
    149 
    150         layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft,
    151                                                 layers[i].fLayer->rect().fTop,
    152                                                 layers[i].fLayer->rect().width(),
    153                                                 layers[i].fLayer->rect().height());
    154     }
    155 }
    156 
    157 void GrLayerHoister::DrawLayers(const SkTDArray<HoistedLayer>& atlased,
    158                                 const SkTDArray<HoistedLayer>& nonAtlased,
    159                                 GrReplacements* replacements) {
    160     // Render the atlased layers that require it
    161     if (atlased.count() > 0) {
    162         // All the atlased layers are rendered into the same GrTexture
    163         SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
    164                                         atlased[0].fLayer->texture()->asRenderTarget(), NULL));
    165 
    166         SkCanvas* atlasCanvas = surface->getCanvas();
    167 
    168         SkPaint paint;
    169         paint.setColor(SK_ColorTRANSPARENT);
    170         paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
    171 
    172         for (int i = 0; i < atlased.count(); ++i) {
    173             GrCachedLayer* layer = atlased[i].fLayer;
    174             const SkPicture* pict = atlased[i].fPicture;
    175 
    176             atlasCanvas->save();
    177 
    178             // Add a rect clip to make sure the rendering doesn't
    179             // extend beyond the boundaries of the atlased sub-rect
    180             SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
    181                                             SkIntToScalar(layer->rect().fTop),
    182                                             SkIntToScalar(layer->rect().width()),
    183                                             SkIntToScalar(layer->rect().height()));
    184             atlasCanvas->clipRect(bound);
    185 
    186             // Since 'clear' doesn't respect the clip we need to draw a rect
    187             // TODO: ensure none of the atlased layers contain a clear call!
    188             atlasCanvas->drawRect(bound, paint);
    189 
    190             // info.fCTM maps the layer's top/left to the origin.
    191             // Since this layer is atlased, the top/left corner needs
    192             // to be offset to the correct location in the backing texture.
    193             SkMatrix initialCTM;
    194             initialCTM.setTranslate(SkIntToScalar(-layer->offset().fX),
    195                                     SkIntToScalar(-layer->offset().fY));
    196             initialCTM.postTranslate(bound.fLeft, bound.fTop);
    197 
    198             atlasCanvas->translate(SkIntToScalar(-layer->offset().fX),
    199                                    SkIntToScalar(-layer->offset().fY));
    200             atlasCanvas->translate(bound.fLeft, bound.fTop);
    201             atlasCanvas->concat(layer->ctm());
    202 
    203             SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound,
    204                                 layer->start()+1, layer->stop(), initialCTM);
    205 
    206             atlasCanvas->restore();
    207         }
    208 
    209         atlasCanvas->flush();
    210     }
    211 
    212     // Render the non-atlased layers that require it
    213     for (int i = 0; i < nonAtlased.count(); ++i) {
    214         GrCachedLayer* layer = nonAtlased[i].fLayer;
    215         const SkPicture* pict = nonAtlased[i].fPicture;
    216 
    217         // Each non-atlased layer has its own GrTexture
    218         SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
    219                                         layer->texture()->asRenderTarget(), NULL));
    220 
    221         SkCanvas* layerCanvas = surface->getCanvas();
    222 
    223         // Add a rect clip to make sure the rendering doesn't
    224         // extend beyond the boundaries of the atlased sub-rect
    225         SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
    226                                         SkIntToScalar(layer->rect().fTop),
    227                                         SkIntToScalar(layer->rect().width()),
    228                                         SkIntToScalar(layer->rect().height()));
    229 
    230         layerCanvas->clipRect(bound); // TODO: still useful?
    231 
    232         layerCanvas->clear(SK_ColorTRANSPARENT);
    233 
    234         SkMatrix initialCTM;
    235         initialCTM.setTranslate(SkIntToScalar(-layer->offset().fX),
    236                                 SkIntToScalar(-layer->offset().fY));
    237 
    238         layerCanvas->translate(SkIntToScalar(-layer->offset().fX),
    239                                SkIntToScalar(-layer->offset().fY));
    240         layerCanvas->concat(layer->ctm());
    241 
    242         SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound,
    243                             layer->start()+1, layer->stop(), initialCTM);
    244 
    245         layerCanvas->flush();
    246     }
    247 
    248     convert_layers_to_replacements(atlased, replacements);
    249     convert_layers_to_replacements(nonAtlased, replacements);
    250 }
    251 
    252 static void unlock_layer_in_cache(GrLayerCache* layerCache,
    253                                   const SkPicture* picture,
    254                                   GrCachedLayer* layer) {
    255     layerCache->unlock(layer);
    256 
    257 #if DISABLE_CACHING
    258     // This code completely clears out the atlas. It is required when
    259     // caching is disabled so the atlas doesn't fill up and force more
    260     // free floating layers
    261     layerCache->purge(picture->uniqueID());
    262 #endif
    263 }
    264 
    265 void GrLayerHoister::UnlockLayers(GrLayerCache* layerCache,
    266                                   const SkTDArray<HoistedLayer>& atlased,
    267                                   const SkTDArray<HoistedLayer>& nonAtlased) {
    268 
    269     for (int i = 0; i < atlased.count(); ++i) {
    270         unlock_layer_in_cache(layerCache, atlased[i].fPicture, atlased[i].fLayer);
    271     }
    272 
    273     for (int i = 0; i < nonAtlased.count(); ++i) {
    274         unlock_layer_in_cache(layerCache, nonAtlased[i].fPicture, nonAtlased[i].fLayer);
    275     }
    276 
    277 #if DISABLE_CACHING
    278     // This code completely clears out the atlas. It is required when
    279     // caching is disabled so the atlas doesn't fill up and force more
    280     // free floating layers
    281     layerCache->purgeAll();
    282 #endif
    283 }
    284 
    285