| Index: src/gpu/GrLayerHoister.cpp
|
| diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp
|
| deleted file mode 100644
|
| index 71c0080d0ef7e6e2756f91ca92d4212df7a59a54..0000000000000000000000000000000000000000
|
| --- 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
|
|
|