diff options
author | 2014-09-24 08:52:18 -0700 | |
---|---|---|
committer | 2014-09-24 08:52:19 -0700 | |
commit | 30d2cc6ff47cb7f981d83e9a536971beec920f61 (patch) | |
tree | 279ab6885df001b92be3ebb2ff696e76c99f471f /src/gpu/GrLayerHoister.cpp | |
parent | 34a9895baf8b2bf95c4f6944a7914be1a74f1524 (diff) |
Update layer hoisting code to correctly render sub-picture layers
The prior code assumed all layers came from a single picture.
BUG=skia:2315
R=bsalomon@google.com
Author: robertphillips@google.com
Review URL: https://codereview.chromium.org/595543002
Diffstat (limited to 'src/gpu/GrLayerHoister.cpp')
-rw-r--r-- | src/gpu/GrLayerHoister.cpp | 125 |
1 files changed, 74 insertions, 51 deletions
diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp index 165716f82d..91d439b304 100644 --- a/src/gpu/GrLayerHoister.cpp +++ b/src/gpu/GrLayerHoister.cpp @@ -14,26 +14,38 @@ #include "SkSurface.h" // Return true if any layers are suitable for hoisting -bool GrLayerHoister::FindLayersToHoist(const GrAccelData *gpuData, +bool GrLayerHoister::FindLayersToHoist(const SkPicture* topLevelPicture, const SkRect& query, - SkTDArray<GrCachedLayer*>* atlased, - SkTDArray<GrCachedLayer*>* nonAtlased, + SkTDArray<HoistedLayer>* atlased, + SkTDArray<HoistedLayer>* nonAtlased, GrLayerCache* layerCache) { bool anyHoisted = false; + SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); + + const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); + if (NULL == topLevelData) { + return false; + } + + const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData); + if (0 == topLevelGPUData->numSaveLayers()) { + return false; + } + // Layer hoisting pre-renders the entire layer since it will be cached and potentially // reused with different clips (e.g., in different tiles). Because of this the // clip will not be limiting the size of the pre-rendered layer. kSaveLayerMaxSize // is used to limit which clips are pre-rendered. static const int kSaveLayerMaxSize = 256; - SkAutoTArray<bool> pullForward(gpuData->numSaveLayers()); + SkAutoTArray<bool> pullForward(topLevelGPUData->numSaveLayers()); // Pre-render all the layers that intersect the query rect - for (int i = 0; i < gpuData->numSaveLayers(); ++i) { + for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { pullForward[i] = false; - const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); + const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); SkRect layerRect = SkRect::MakeXYWH(SkIntToScalar(info.fOffset.fX), SkIntToScalar(info.fOffset.fY), @@ -61,14 +73,15 @@ bool GrLayerHoister::FindLayersToHoist(const GrAccelData *gpuData, return false; } - atlased->setReserve(atlased->reserved() + gpuData->numSaveLayers()); + atlased->setReserve(atlased->reserved() + topLevelGPUData->numSaveLayers()); // Generate the layer and/or ensure it is locked - for (int i = 0; i < gpuData->numSaveLayers(); ++i) { + for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { if (pullForward[i]) { - const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); + const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); + const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; - GrCachedLayer* layer = layerCache->findLayerOrCreate(info.fPictureID, + GrCachedLayer* layer = layerCache->findLayerOrCreate(pict->uniqueID(), info.fSaveLayerOpID, info.fRestoreOpID, info.fOffset, @@ -89,11 +102,16 @@ bool GrLayerHoister::FindLayersToHoist(const GrAccelData *gpuData, } if (needsRendering) { + HoistedLayer* info; + if (layer->isAtlased()) { - *atlased->append() = layer; + info = atlased->append(); } else { - *nonAtlased->append() = layer; + info = nonAtlased->append(); } + + info->fLayer = layer; + info->fPicture = pict; } } } @@ -107,42 +125,43 @@ static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* re result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); } -static void convert_layers_to_replacements(const SkTDArray<GrCachedLayer*>& layers, +static void convert_layers_to_replacements(const SkTDArray<GrLayerHoister::HoistedLayer>& layers, GrReplacements* replacements) { // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer? for (int i = 0; i < layers.count(); ++i) { GrReplacements::ReplacementInfo* layerInfo = replacements->push(); - layerInfo->fStart = layers[i]->start(); - layerInfo->fStop = layers[i]->stop(); - layerInfo->fPos = layers[i]->offset();; + layerInfo->fStart = layers[i].fLayer->start(); + layerInfo->fStop = layers[i].fLayer->stop(); + layerInfo->fPos = layers[i].fLayer->offset();; SkBitmap bm; - wrap_texture(layers[i]->texture(), - !layers[i]->isAtlased() ? layers[i]->rect().width() - : layers[i]->texture()->width(), - !layers[i]->isAtlased() ? layers[i]->rect().height() - : layers[i]->texture()->height(), + wrap_texture(layers[i].fLayer->texture(), + !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().width() + : layers[i].fLayer->texture()->width(), + !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().height() + : layers[i].fLayer->texture()->height(), &bm); layerInfo->fImage = SkImage::NewTexture(bm); - layerInfo->fPaint = layers[i]->paint() ? SkNEW_ARGS(SkPaint, (*layers[i]->paint())) : NULL; + layerInfo->fPaint = layers[i].fLayer->paint() + ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint())) + : NULL; - layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i]->rect().fLeft, - layers[i]->rect().fTop, - layers[i]->rect().width(), - layers[i]->rect().height()); + layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft, + layers[i].fLayer->rect().fTop, + layers[i].fLayer->rect().width(), + layers[i].fLayer->rect().height()); } } -void GrLayerHoister::DrawLayers(const SkPicture* picture, - const SkTDArray<GrCachedLayer*>& atlased, - const SkTDArray<GrCachedLayer*>& nonAtlased, +void GrLayerHoister::DrawLayers(const SkTDArray<HoistedLayer>& atlased, + const SkTDArray<HoistedLayer>& nonAtlased, GrReplacements* replacements) { // Render the atlased layers that require it if (atlased.count() > 0) { // All the atlased layers are rendered into the same GrTexture SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( - atlased[0]->texture()->asRenderTarget(), NULL)); + atlased[0].fLayer->texture()->asRenderTarget(), NULL)); SkCanvas* atlasCanvas = surface->getCanvas(); @@ -151,7 +170,8 @@ void GrLayerHoister::DrawLayers(const SkPicture* picture, paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref(); for (int i = 0; i < atlased.count(); ++i) { - GrCachedLayer* layer = atlased[i]; + GrCachedLayer* layer = atlased[i].fLayer; + const SkPicture* pict = atlased[i].fPicture; atlasCanvas->save(); @@ -180,7 +200,7 @@ void GrLayerHoister::DrawLayers(const SkPicture* picture, atlasCanvas->translate(bound.fLeft, bound.fTop); atlasCanvas->concat(layer->ctm()); - SkRecordPartialDraw(*picture->fRecord.get(), atlasCanvas, bound, + SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound, layer->start()+1, layer->stop(), initialCTM); atlasCanvas->restore(); @@ -191,7 +211,8 @@ void GrLayerHoister::DrawLayers(const SkPicture* picture, // Render the non-atlased layers that require it for (int i = 0; i < nonAtlased.count(); ++i) { - GrCachedLayer* layer = nonAtlased[i]; + GrCachedLayer* layer = nonAtlased[i].fLayer; + const SkPicture* pict = nonAtlased[i].fPicture; // Each non-atlased layer has its own GrTexture SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( @@ -218,7 +239,7 @@ void GrLayerHoister::DrawLayers(const SkPicture* picture, SkIntToScalar(-layer->offset().fY)); layerCanvas->concat(layer->ctm()); - SkRecordPartialDraw(*picture->fRecord.get(), layerCanvas, bound, + SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound, layer->start()+1, layer->stop(), initialCTM); layerCanvas->flush(); @@ -228,33 +249,35 @@ void GrLayerHoister::DrawLayers(const SkPicture* picture, convert_layers_to_replacements(nonAtlased, replacements); } -void GrLayerHoister::UnlockLayers(GrLayerCache* layerCache, const SkPicture* picture) { - SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); +static void unlock_layer_in_cache(GrLayerCache* layerCache, + const SkPicture* picture, + GrCachedLayer* layer) { + layerCache->unlock(layer); - const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key); - SkASSERT(data); +#if DISABLE_CACHING + // This code completely clears out the atlas. It is required when + // caching is disabled so the atlas doesn't fill up and force more + // free floating layers + layerCache->purge(picture->uniqueID()); +#endif +} - const GrAccelData *gpuData = static_cast<const GrAccelData*>(data); - SkASSERT(0 != gpuData->numSaveLayers()); +void GrLayerHoister::UnlockLayers(GrLayerCache* layerCache, + const SkTDArray<HoistedLayer>& atlased, + const SkTDArray<HoistedLayer>& nonAtlased) { - // unlock the layers - for (int i = 0; i < gpuData->numSaveLayers(); ++i) { - const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); + for (int i = 0; i < atlased.count(); ++i) { + unlock_layer_in_cache(layerCache, atlased[i].fPicture, atlased[i].fLayer); + } - GrCachedLayer* layer = layerCache->findLayer(picture->uniqueID(), - info.fSaveLayerOpID, - info.fRestoreOpID, - info.fOffset, - info.fOriginXform); - layerCache->unlock(layer); + for (int i = 0; i < nonAtlased.count(); ++i) { + unlock_layer_in_cache(layerCache, nonAtlased[i].fPicture, nonAtlased[i].fLayer); } #if DISABLE_CACHING // This code completely clears out the atlas. It is required when // caching is disabled so the atlas doesn't fill up and force more // free floating layers - layerCache->purge(picture->uniqueID()); - layerCache->purgeAll(); #endif } |