diff options
author | 2014-12-11 08:20:31 -0800 | |
---|---|---|
committer | 2014-12-11 08:20:31 -0800 | |
commit | 7b9e8a4b6af0f3df9bf20a5fdc0977bcd7c3c1ab (patch) | |
tree | 972d87273c867a699c51036768c5e9588766b779 /src/gpu | |
parent | b511dfe3264f1f32a8fc7d2af35eec4ffc80b250 (diff) |
Apply the layer's image filter to the hoisted image
Exposing SkSurface_Gpu makes me sad and I would welcome alternatives.
This change is desireable since it greatly decreases the render target swaps.
Review URL: https://codereview.chromium.org/792923002
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrLayerCache.h | 15 | ||||
-rw-r--r-- | src/gpu/GrLayerHoister.cpp | 40 | ||||
-rw-r--r-- | src/gpu/GrLayerHoister.h | 10 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 6 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 8 |
5 files changed, 71 insertions, 8 deletions
diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h index b9b59d06bc..0ea23b3fc7 100644 --- a/src/gpu/GrLayerCache.h +++ b/src/gpu/GrLayerCache.h @@ -12,6 +12,7 @@ #include "GrRect.h" #include "SkChecksum.h" +#include "SkImageFilter.h" #include "SkMessageBus.h" #include "SkPicture.h" #include "SkTDynamicHash.h" @@ -151,16 +152,23 @@ public: , fStop(stop) , fBounds(bounds) , fPaint(paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL) + , fFilter(NULL) , fTexture(NULL) , fRect(SkIRect::MakeEmpty()) , fPlot(NULL) , fUses(0) , fLocked(false) { SkASSERT(SK_InvalidGenID != pictureID); + + if (fPaint) { + fFilter = SkSafeRef(fPaint->getImageFilter()); + fPaint->setImageFilter(NULL); + } } ~GrCachedLayer() { SkSafeUnref(fTexture); + SkSafeUnref(fFilter); SkDELETE(fPaint); } @@ -179,6 +187,7 @@ public: } GrTexture* texture() { return fTexture; } const SkPaint* paint() const { return fPaint; } + const SkImageFilter* filter() const { return fFilter; } const SkIRect& rect() const { return fRect; } void setPlot(GrPlot* plot) { @@ -207,7 +216,11 @@ private: // The paint used when dropping the layer down into the owning canvas. // Can be NULL. This class makes a copy for itself. - const SkPaint* fPaint; + SkPaint* fPaint; + + // The imagefilter that needs to be applied to the layer prior to it being + // composited with the rest of the scene. + const SkImageFilter* fFilter; // fTexture is a ref on the atlasing texture for atlased layers and a // ref on a GrTexture for non-atlased textures. diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp index 5d2d5493b4..493e2f752a 100644 --- a/src/gpu/GrLayerHoister.cpp +++ b/src/gpu/GrLayerHoister.cpp @@ -10,10 +10,12 @@ #include "GrRecordReplaceDraw.h" #include "SkCanvas.h" +#include "SkGpuDevice.h" #include "SkGrPixelRef.h" #include "SkLayerInfo.h" #include "SkRecordDraw.h" #include "SkSurface.h" +#include "SkSurface_Gpu.h" // Create the layer information for the hoisted layer and secure the // required texture/render target resources. @@ -200,6 +202,7 @@ void GrLayerHoister::DrawLayersToAtlas(GrContext* context, SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) SkASSERT(!layerPaint || !layerPaint->getImageFilter()); + SkASSERT(!layer->filter()); atlasCanvas->save(); @@ -231,6 +234,37 @@ void GrLayerHoister::DrawLayersToAtlas(GrContext* context, } } +void GrLayerHoister::FilterLayer(GrContext* context, SkGpuDevice* device, GrCachedLayer* layer) { + SkASSERT(layer->filter()); + + static const int kDefaultCacheSize = 32 * 1024 * 1024; + + if (layer->filter()->canFilterImageGPU()) { + SkBitmap filteredBitmap; + SkIPoint offset = SkIPoint::Make(0, 0); + + SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop); + SkIRect clipBounds = layer->rect(); + + // This cache is transient, and is freed (along with all its contained + // textures) when it goes out of scope. + SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kDefaultCacheSize)); + SkImageFilter::Context filterContext(SkMatrix::I(), clipBounds, cache); + + if (!device->filterTexture(context, layer->texture(), layer->filter(), + filterContext, &filteredBitmap, &offset)) { + // Filtering failed. Press on with the unfiltered version + return; + } + + // TODO: need to fix up offset + SkASSERT(0 == offset.fX && 0 == offset.fY); + + SkIRect newRect = SkIRect::MakeWH(filteredBitmap.width(), filteredBitmap.height()); + layer->setTexture(filteredBitmap.getTexture(), newRect); + } +} + void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) { for (int i = 0; i < layers.count(); ++i) { GrCachedLayer* layer = layers[i].fLayer; @@ -263,6 +297,12 @@ void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLay layer->start()+1, layer->stop(), initialCTM); layerCanvas->flush(); + + if (layer->filter()) { + SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(surface.get()); + + FilterLayer(context, gpuSurf->getDevice(), layer); + } } } diff --git a/src/gpu/GrLayerHoister.h b/src/gpu/GrLayerHoister.h index 2d68a94a88..9668ba60d5 100644 --- a/src/gpu/GrLayerHoister.h +++ b/src/gpu/GrLayerHoister.h @@ -13,6 +13,7 @@ struct GrCachedLayer; class GrReplacements; +class SkGpuDevice; struct SkRect; class GrHoistedLayer { @@ -102,6 +103,15 @@ public: @param context Owner of the layer cache (and thus the layers) */ static void PurgeCache(GrContext* context); + +private: + /** Update the GrTexture in 'layer' with its filtered version + @param context Owner of the layer cache (and thus the layers) + @param device Required by the filtering code + @param layer A layer needing filtering prior to being composited + */ + static void FilterLayer(GrContext* context, SkGpuDevice* device, GrCachedLayer* layer); + }; #endif diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index c0439f5e89..4c9f0e2b7d 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1528,9 +1528,9 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, return; } - const SkBitmap& bm = dev->accessBitmap(false); - int w = bm.width(); - int h = bm.height(); + const SkImageInfo ii = dev->imageInfo(); + int w = ii.width(); + int h = ii.height(); SkImageFilter* filter = paint.getImageFilter(); // This bitmap will own the filtered result as a texture. diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index 2fb6de7eb8..9023a630e8 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -124,6 +124,10 @@ public: const SkImageFilter::Context&, SkBitmap*, SkIPoint*) SK_OVERRIDE; + bool filterTexture(GrContext*, GrTexture*, const SkImageFilter*, + const SkImageFilter::Context&, + SkBitmap* result, SkIPoint* offset); + protected: virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int, int) SK_OVERRIDE; virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int, int) SK_OVERRIDE; @@ -203,10 +207,6 @@ private: bool drawDashLine(const SkPoint pts[2], const SkPaint& paint); - bool filterTexture(GrContext*, GrTexture*, const SkImageFilter*, - const SkImageFilter::Context&, - SkBitmap* result, SkIPoint* offset); - static SkPicture::AccelData::Key ComputeAccelDataKey(); typedef SkBaseDevice INHERITED; |