diff options
Diffstat (limited to 'src/gpu/GrLayerHoister.cpp')
-rw-r--r-- | src/gpu/GrLayerHoister.cpp | 402 |
1 files changed, 0 insertions, 402 deletions
diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp deleted file mode 100644 index 71c0080d0e..0000000000 --- a/src/gpu/GrLayerHoister.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkBigPicture.h" -#include "SkCanvas.h" -#include "SkImageFilterCache.h" -#include "SkLayerInfo.h" -#include "SkRecordDraw.h" -#include "SkSpecialImage.h" -#include "SkSurface.h" - -#include "GrLayerHoister.h" - -#if !defined(SK_IGNORE_GPU_LAYER_HOISTING) && SK_SUPPORT_GPU - -#include "GrContext.h" -#include "GrLayerCache.h" -#include "GrRecordReplaceDraw.h" - -// Create the layer information for the hoisted layer and secure the -// required texture/render target resources. -static void prepare_for_hoisting(GrLayerCache* layerCache, - const SkPicture* topLevelPicture, - const SkMatrix& initialMat, - const SkLayerInfo::BlockInfo& info, - const SkIRect& srcIR, - const SkIRect& dstIR, - SkTDArray<GrHoistedLayer>* needRendering, - SkTDArray<GrHoistedLayer>* recycled, - bool attemptToAtlas, - int numSamples) { - const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture; - - GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->uniqueID(), - SkToInt(info.fSaveLayerOpID), - SkToInt(info.fRestoreOpID), - srcIR, - dstIR, - initialMat, - info.fKey, - info.fKeySize, - info.fPaint); - GrSurfaceDesc desc; - desc.fFlags = kRenderTarget_GrSurfaceFlag; - desc.fWidth = srcIR.width(); - desc.fHeight = srcIR.height(); - desc.fConfig = kSkia8888_GrPixelConfig; - desc.fSampleCnt = numSamples; - - bool locked, needsRendering; - if (attemptToAtlas) { - locked = layerCache->tryToAtlas(layer, desc, &needsRendering); - } else { - locked = layerCache->lock(layer, desc, &needsRendering); - } - if (!locked) { - // GPU resources could not be secured for the hoisting of this layer - return; - } - - if (attemptToAtlas) { - SkASSERT(layer->isAtlased()); - } - - GrHoistedLayer* hl; - - if (needsRendering) { - if (!attemptToAtlas) { - SkASSERT(!layer->isAtlased()); - } - hl = needRendering->append(); - } else { - hl = recycled->append(); - } - - layerCache->addUse(layer); - hl->fLayer = layer; - hl->fPicture = pict; - hl->fLocalMat = info.fLocalMat; - hl->fInitialMat = initialMat; - hl->fPreMat = initialMat; - hl->fPreMat.preConcat(info.fPreMat); -} - -// Compute the source rect and return false if it is empty. -static bool compute_source_rect(const SkLayerInfo::BlockInfo& info, const SkMatrix& initialMat, - const SkIRect& dstIR, SkIRect* srcIR) { - SkIRect clipBounds = dstIR; - - SkMatrix totMat = initialMat; - totMat.preConcat(info.fPreMat); - totMat.preConcat(info.fLocalMat); - - if (info.fPaint && info.fPaint->getImageFilter()) { - clipBounds = info.fPaint->getImageFilter()->filterBounds(clipBounds, totMat); - } - - if (!info.fSrcBounds.isEmpty()) { - SkRect r; - - totMat.mapRect(&r, info.fSrcBounds); - r.roundOut(srcIR); - - if (!srcIR->intersect(clipBounds)) { - return false; - } - } else { - *srcIR = clipBounds; - } - - return true; -} - -// Atlased layers must be small enough to fit in the atlas, not have a -// paint with an image filter and be neither nested nor nesting. -// TODO: allow leaf nested layers to appear in the atlas. -void GrLayerHoister::FindLayersToAtlas(GrContext* context, - const SkPicture* topLevelPicture, - const SkMatrix& initialMat, - const SkRect& query, - SkTDArray<GrHoistedLayer>* atlased, - SkTDArray<GrHoistedLayer>* recycled, - int numSamples) { - if (0 != numSamples) { - // MSAA layers are currently never atlased - return; - } - - GrLayerCache* layerCache = context->getLayerCache(); - layerCache->processDeletedPictures(); - - const SkBigPicture::AccelData* topLevelData = nullptr; - if (const SkBigPicture* bp = topLevelPicture->asSkBigPicture()) { - topLevelData = bp->accelData(); - } - if (!topLevelData) { - return; - } - - const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData); - if (0 == topLevelGPUData->numBlocks()) { - return; - } - - atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks()); - - for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) { - const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i); - - // TODO: ignore perspective projected layers here? - bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested || - (info.fPaint && info.fPaint->getImageFilter()); - - if (disallowAtlasing) { - continue; - } - - SkRect layerRect; - initialMat.mapRect(&layerRect, info.fBounds); - if (!layerRect.intersect(query)) { - continue; - } - - const SkIRect dstIR = layerRect.roundOut(); - - SkIRect srcIR; - - if (!compute_source_rect(info, initialMat, dstIR, &srcIR) || - !GrLayerCache::PlausiblyAtlasable(srcIR.width(), srcIR.height())) { - continue; - } - - prepare_for_hoisting(layerCache, topLevelPicture, initialMat, - info, srcIR, dstIR, atlased, recycled, true, 0); - } - -} - -void GrLayerHoister::FindLayersToHoist(GrContext* context, - const SkPicture* topLevelPicture, - const SkMatrix& initialMat, - const SkRect& query, - SkTDArray<GrHoistedLayer>* needRendering, - SkTDArray<GrHoistedLayer>* recycled, - int numSamples) { - GrLayerCache* layerCache = context->getLayerCache(); - - layerCache->processDeletedPictures(); - - const SkBigPicture::AccelData* topLevelData = nullptr; - if (const SkBigPicture* bp = topLevelPicture->asSkBigPicture()) { - topLevelData = bp->accelData(); - } - if (!topLevelData) { - return; - } - - const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData); - if (0 == topLevelGPUData->numBlocks()) { - return; - } - - // Find and prepare for hoisting all the layers that intersect the query rect - for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) { - const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i); - if (info.fIsNested) { - // Parent layers are currently hoisted while nested layers are not. - continue; - } - - SkRect layerRect; - initialMat.mapRect(&layerRect, info.fBounds); - if (!layerRect.intersect(query)) { - continue; - } - - const SkIRect dstIR = layerRect.roundOut(); - - SkIRect srcIR; - if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) { - continue; - } - - prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, srcIR, dstIR, - needRendering, recycled, false, numSamples); - } -} - -void GrLayerHoister::DrawLayersToAtlas(GrContext* context, - const SkTDArray<GrHoistedLayer>& atlased) { - if (atlased.count() > 0) { - // All the atlased layers are rendered into the same GrTexture - SkSurfaceProps props(0, kUnknown_SkPixelGeometry); - sk_sp<SkSurface> surface(SkSurface::MakeRenderTargetDirect( - atlased[0].fLayer->texture()->asRenderTarget(), &props)); - - SkCanvas* atlasCanvas = surface->getCanvas(); - - for (int i = 0; i < atlased.count(); ++i) { - const GrCachedLayer* layer = atlased[i].fLayer; - const SkBigPicture* pict = atlased[i].fPicture->asSkBigPicture(); - if (!pict) { - // TODO: can we assume / assert this? - continue; - } - const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop); - SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) - - SkASSERT(!layerPaint || !layerPaint->getImageFilter()); - SkASSERT(!layer->filter()); - - atlasCanvas->save(); - - // Add a rect clip to make sure the rendering doesn't - // extend beyond the boundaries of the atlased sub-rect - const SkRect bound = SkRect::Make(layer->rect()); - atlasCanvas->clipRect(bound); - atlasCanvas->clear(0); - - // '-offset' maps the layer's top/left to the origin. - // Since this layer is atlased, the top/left corner needs - // to be offset to the correct location in the backing texture. - SkMatrix initialCTM; - initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY)); - initialCTM.preTranslate(bound.fLeft, bound.fTop); - initialCTM.preConcat(atlased[i].fPreMat); - - atlasCanvas->setMatrix(initialCTM); - atlasCanvas->concat(atlased[i].fLocalMat); - - pict->partialPlayback(atlasCanvas, layer->start() + 1, layer->stop(), initialCTM); - atlasCanvas->restore(); - } - - atlasCanvas->flush(); - } -} - -void GrLayerHoister::FilterLayer(GrContext* context, - const SkSurfaceProps* props, - const GrHoistedLayer& info) { - GrCachedLayer* layer = info.fLayer; - - SkASSERT(layer->filter()); - - static const int kDefaultCacheSize = 32 * 1024 * 1024; - - const SkIPoint filterOffset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop); - - SkMatrix totMat(info.fPreMat); - totMat.preConcat(info.fLocalMat); - totMat.postTranslate(-SkIntToScalar(filterOffset.fX), -SkIntToScalar(filterOffset.fY)); - - SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); - const SkIRect& clipBounds = layer->rect(); - - // This cache is transient, and is freed (along with all its contained - // textures) when it goes out of scope. - SkAutoTUnref<SkImageFilterCache> cache(SkImageFilterCache::Create(kDefaultCacheSize)); - SkImageFilter::Context filterContext(totMat, clipBounds, cache); - - // TODO: should the layer hoister store stand alone layers as SkSpecialImages internally? - SkASSERT(layer->rect().width() == layer->texture()->width() && - layer->rect().height() == layer->texture()->height()); - const SkIRect subset = SkIRect::MakeWH(layer->rect().width(), layer->rect().height()); - sk_sp<SkSpecialImage> img(SkSpecialImage::MakeFromGpu(subset, - kNeedNewImageUniqueID_SpecialImage, - sk_ref_sp(layer->texture()), - props)); - - SkIPoint offset = SkIPoint::Make(0, 0); - sk_sp<SkSpecialImage> result(layer->filter()->filterImage(img.get(), - filterContext, - &offset)); - if (!result) { - // Filtering failed. Press on with the unfiltered version. - return; - } - - SkASSERT(result->isTextureBacked()); - sk_sp<GrTexture> texture(result->asTextureRef(context)); - layer->setTexture(texture.get(), result->subset(), false); - layer->setOffset(offset); -} - -void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) { - for (int i = 0; i < layers.count(); ++i) { - GrCachedLayer* layer = layers[i].fLayer; - const SkBigPicture* pict = layers[i].fPicture->asSkBigPicture(); - if (!pict) { - // TODO: can we assume / assert this? - continue; - } - const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop); - - // Each non-atlased layer has its own GrTexture - SkSurfaceProps props(0, kUnknown_SkPixelGeometry); - auto surface(SkSurface::MakeRenderTargetDirect( - layer->texture()->asRenderTarget(), &props)); - - SkCanvas* layerCanvas = surface->getCanvas(); - - SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); - - // Add a rect clip to make sure the rendering doesn't - // extend beyond the boundaries of the layer - const SkRect bound = SkRect::Make(layer->rect()); - layerCanvas->clipRect(bound); - layerCanvas->clear(SK_ColorTRANSPARENT); - - SkMatrix initialCTM; - initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY)); - initialCTM.preConcat(layers[i].fPreMat); - - layerCanvas->setMatrix(initialCTM); - layerCanvas->concat(layers[i].fLocalMat); - - pict->partialPlayback(layerCanvas, layer->start()+1, layer->stop(), initialCTM); - layerCanvas->flush(); - - if (layer->filter()) { - FilterLayer(context, &surface->props(), layers[i]); - } - } -} - -void GrLayerHoister::UnlockLayers(GrContext* context, - const SkTDArray<GrHoistedLayer>& layers) { - GrLayerCache* layerCache = context->getLayerCache(); - - for (int i = 0; i < layers.count(); ++i) { - layerCache->removeUse(layers[i].fLayer); - } - - SkDEBUGCODE(layerCache->validate();) -} - -void GrLayerHoister::Begin(GrContext* context) { - GrLayerCache* layerCache = context->getLayerCache(); - - layerCache->begin(); -} - -void GrLayerHoister::End(GrContext* context) { - GrLayerCache* layerCache = context->getLayerCache(); - -#if !GR_CACHE_HOISTED_LAYERS - - // 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->purgeAll(); -#endif - - layerCache->end(); -} - -#endif |