From 83c17fa56b23159166394cb3feb431ffafbbab48 Mon Sep 17 00:00:00 2001 From: robertphillips Date: Fri, 18 Mar 2016 08:14:27 -0700 Subject: [PATCH] Add SkSpecialImage::makeTextureImage entry point This is calved off of: https://codereview.chromium.org/1785643003 (Switch SkBlurImageFilter over to new onFilterImage interface) GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1813813002 Committed: https://skia.googlesource.com/skia/+/05849018c85403a34b88819db1c4bcf713b70a2b Review URL: https://codereview.chromium.org/1813813002 --- src/core/SkImageFilter.cpp | 13 ++++++- src/core/SkSpecialImage.cpp | 40 ++++++++++++++++++- src/core/SkSpecialImage.h | 11 ++++++ tests/SpecialImageTest.cpp | 78 ++++++++++++++++++++++++++++++++++++- 4 files changed, 139 insertions(+), 3 deletions(-) diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 1a4c876d61..4ae839c3d4 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -596,7 +596,18 @@ SkSpecialImage* SkImageFilter::filterInput(int index, return SkRef(src); } - return input->filterImage(src, this->mapContext(ctx), offset); + SkAutoTUnref result(input->filterImage(src, this->mapContext(ctx), offset)); + +#if SK_SUPPORT_GPU + if (src->peekTexture() && result && !result->peekTexture()) { + // Keep the result on the GPU - this is still required for some + // image filters that don't support GPU in all cases + GrContext* context = src->peekTexture()->getContext(); + return result->makeTextureImage(src->internal_getProxy(), context).release(); + } +#endif + + return result.release(); } #if SK_SUPPORT_GPU diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp index e90c655a58..991e163515 100644 --- a/src/core/SkSpecialImage.cpp +++ b/src/core/SkSpecialImage.cpp @@ -4,10 +4,16 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file */ +#include "SkSpecialImage.h" + +#if SK_SUPPORT_GPU +#include "GrTexture.h" +#include "GrTextureParams.h" +#include "SkGr.h" +#endif #include "SkCanvas.h" #include "SkImage_Base.h" -#include "SkSpecialImage.h" #include "SkSpecialSurface.h" /////////////////////////////////////////////////////////////////////////////// @@ -42,6 +48,38 @@ static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) { return static_cast(image); } +sk_sp SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* proxy, + GrContext* context) { +#if SK_SUPPORT_GPU + if (!context) { + return nullptr; + } + if (GrTexture* peek = as_SIB(this)->peekTexture()) { + return peek->getContext() == context ? sk_sp(SkRef(this)) : nullptr; + } + + SkBitmap bmp; + if (!this->internal_getBM(&bmp)) { + return nullptr; + } + + SkAutoTUnref resultTex( + GrRefCachedBitmapTexture(context, bmp, GrTextureParams::ClampNoFilter())); + if (!resultTex) { + return nullptr; + } + + SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; + + return SkSpecialImage::MakeFromGpu(proxy, + SkIRect::MakeWH(resultTex->width(), resultTex->height()), + this->uniqueID(), + resultTex, at); +#else + return nullptr; +#endif +} + void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const { return as_SIB(this)->onDraw(canvas, x, y, paint); } diff --git a/src/core/SkSpecialImage.h b/src/core/SkSpecialImage.h index 1a01a5abc7..47ad6ccab7 100644 --- a/src/core/SkSpecialImage.h +++ b/src/core/SkSpecialImage.h @@ -14,12 +14,16 @@ // remove this when internal_getProxy goes away (see skbug.com/4965) #include "SkImageFilter.h" +#include "SkImageInfo.h" // for SkAlphaType + +class GrContext; class GrTexture; class SkBitmap; class SkCanvas; class SkImage; struct SkImageInfo; class SkPaint; +class SkPixmap; class SkSpecialSurface; enum { @@ -50,6 +54,13 @@ public: virtual bool isOpaque() const { return false; } virtual size_t getSize() const = 0; + /** + * Ensures that a special image is backed by a texture (when GrContext is non-null). If no + * transformation is required, the returned image may be the same as this special image. + * If this special image is from a different GrContext, this will fail. + */ + sk_sp makeTextureImage(SkImageFilter::Proxy*, GrContext*); + /** * Draw this SpecialImage into the canvas. */ diff --git a/tests/SpecialImageTest.cpp b/tests/SpecialImageTest.cpp index 233ce2cee1..3240fbd3a7 100644 --- a/tests/SpecialImageTest.cpp +++ b/tests/SpecialImageTest.cpp @@ -174,6 +174,81 @@ DEF_TEST(SpecialImage_Pixmap, reporter) { #if SK_SUPPORT_GPU + +static void test_texture_backed(skiatest::Reporter* reporter, + const sk_sp& orig, + const sk_sp& gpuBacked) { + REPORTER_ASSERT(reporter, gpuBacked); + REPORTER_ASSERT(reporter, gpuBacked->peekTexture()); + REPORTER_ASSERT(reporter, gpuBacked->uniqueID() == orig->uniqueID()); + REPORTER_ASSERT(reporter, gpuBacked->subset().width() == orig->subset().width() && + gpuBacked->subset().height() == orig->subset().height()); +} + +// Test out the SkSpecialImage::makeTextureImage entry point +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_MakeTexture, reporter, context) { + SkBitmap bm = create_bm(); + + const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize); + + { + // raster + sk_sp rasterImage(SkSpecialImage::MakeFromRaster( + nullptr, + SkIRect::MakeWH(kFullSize, + kFullSize), + bm)); + + { + sk_sp fromRaster(rasterImage->makeTextureImage(nullptr, context)); + test_texture_backed(reporter, rasterImage, fromRaster); + } + + { + sk_sp subRasterImage(rasterImage->makeSubset(subset)); + + sk_sp fromSubRaster(subRasterImage->makeTextureImage(nullptr, context)); + test_texture_backed(reporter, subRasterImage, fromSubRaster); + } + } + + { + // gpu + GrSurfaceDesc desc; + desc.fConfig = kSkia8888_GrPixelConfig; + desc.fFlags = kNone_GrSurfaceFlags; + desc.fWidth = kFullSize; + desc.fHeight = kFullSize; + + SkAutoTUnref texture(context->textureProvider()->createTexture(desc, + SkBudgeted::kNo, + bm.getPixels(), + 0)); + if (!texture) { + return; + } + + sk_sp gpuImage(SkSpecialImage::MakeFromGpu( + nullptr, + SkIRect::MakeWH(kFullSize, + kFullSize), + kNeedNewImageUniqueID_SpecialImage, + texture)); + + { + sk_sp fromGPU(gpuImage->makeTextureImage(nullptr, context)); + test_texture_backed(reporter, gpuImage, fromGPU); + } + + { + sk_sp subGPUImage(gpuImage->makeSubset(subset)); + + sk_sp fromSubGPU(subGPUImage->makeTextureImage(nullptr, context)); + test_texture_backed(reporter, subGPUImage, fromSubGPU); + } + } +} + DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, context) { SkBitmap bm = create_bm(); @@ -183,7 +258,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, context) { desc.fWidth = kFullSize; desc.fHeight = kFullSize; - SkAutoTUnref texture(context->textureProvider()->createTexture(desc, SkBudgeted::kNo, + SkAutoTUnref texture(context->textureProvider()->createTexture(desc, + SkBudgeted::kNo, bm.getPixels(), 0)); if (!texture) { return; -- 2.34.1