diff options
-rw-r--r-- | gyp/gpu.gyp | 1 | ||||
-rw-r--r-- | gyp/gpu.gypi | 1 | ||||
-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 | ||||
-rw-r--r-- | src/image/SkSurface_Gpu.cpp | 22 | ||||
-rw-r--r-- | src/image/SkSurface_Gpu.h | 42 |
9 files changed, 116 insertions, 29 deletions
diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index 631945607d..e835e34850 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -96,6 +96,7 @@ '../include/gpu', '../src/core', '../src/gpu', + '../src/image/', ], 'sources': [ '<@(skgpu_sources)', diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 32603fedf2..1570ab4cc5 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -299,6 +299,7 @@ '<(skia_src_path)/gpu/SkGrTexturePixelRef.cpp', '<(skia_src_path)/image/SkImage_Gpu.cpp', + '<(skia_src_path)/image/SkSurface_Gpu.h', '<(skia_src_path)/image/SkSurface_Gpu.cpp', '<(skia_src_path)/gpu/gl/SkGLContext.cpp' 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; diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp index 848709445d..e58375b53b 100644 --- a/src/image/SkSurface_Gpu.cpp +++ b/src/image/SkSurface_Gpu.cpp @@ -10,30 +10,10 @@ #include "SkImage_Base.h" #include "SkCanvas.h" #include "SkGpuDevice.h" +#include "SkSurface_Gpu.h" #if SK_SUPPORT_GPU -class SkSurface_Gpu : public SkSurface_Base { -public: - SK_DECLARE_INST_COUNT(SkSurface_Gpu) - - SkSurface_Gpu(GrRenderTarget*, const SkSurfaceProps*, bool doClear); - virtual ~SkSurface_Gpu(); - - virtual SkCanvas* onNewCanvas() SK_OVERRIDE; - virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE; - virtual SkImage* onNewImageSnapshot() SK_OVERRIDE; - virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, - const SkPaint*) SK_OVERRIDE; - virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE; - virtual void onDiscard() SK_OVERRIDE; - -private: - SkGpuDevice* fDevice; - - typedef SkSurface_Base INHERITED; -}; - /////////////////////////////////////////////////////////////////////////////// SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget, const SkSurfaceProps* props, diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h new file mode 100644 index 0000000000..a02eb3e904 --- /dev/null +++ b/src/image/SkSurface_Gpu.h @@ -0,0 +1,42 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkSurface_Gpu_DEFINED +#define SkSurface_Gpu_DEFINED + +#include "SkSurface_Base.h" + +#if SK_SUPPORT_GPU + +class SkGpuDevice; + +class SkSurface_Gpu : public SkSurface_Base { +public: + SK_DECLARE_INST_COUNT(SkSurface_Gpu) + + SkSurface_Gpu(GrRenderTarget*, const SkSurfaceProps*, bool doClear); + virtual ~SkSurface_Gpu(); + + virtual SkCanvas* onNewCanvas() SK_OVERRIDE; + virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE; + virtual SkImage* onNewImageSnapshot() SK_OVERRIDE; + virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, + const SkPaint*) SK_OVERRIDE; + virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE; + virtual void onDiscard() SK_OVERRIDE; + + SkGpuDevice* getDevice() { return fDevice; } + +private: + SkGpuDevice* fDevice; + + typedef SkSurface_Base INHERITED; +}; + +#endif // SK_SUPPORT_GPU + +#endif // SkSurface_Gpu_DEFINED |