diff options
author | robertphillips <robertphillips@google.com> | 2016-03-18 08:14:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-18 08:14:27 -0700 |
commit | 83c17fa56b23159166394cb3feb431ffafbbab48 (patch) | |
tree | 5a13d5597db58b5baccd2ac599706e1c4f24a8bd | |
parent | 2b1b40e11afc41452b4d2f74cdebb1b6e6f7cc96 (diff) |
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
-rw-r--r-- | src/core/SkImageFilter.cpp | 13 | ||||
-rw-r--r-- | src/core/SkSpecialImage.cpp | 40 | ||||
-rw-r--r-- | src/core/SkSpecialImage.h | 11 | ||||
-rw-r--r-- | 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<SkSpecialImage> 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<const SkSpecialImage_Base*>(image); } +sk_sp<SkSpecialImage> 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<SkSpecialImage>(SkRef(this)) : nullptr; + } + + SkBitmap bmp; + if (!this->internal_getBM(&bmp)) { + return nullptr; + } + + SkAutoTUnref<GrTexture> 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 { @@ -51,6 +55,13 @@ public: 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<SkSpecialImage> makeTextureImage(SkImageFilter::Proxy*, GrContext*); + + /** * Draw this SpecialImage into the canvas. */ void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const; 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<SkSpecialImage>& orig, + const sk_sp<SkSpecialImage>& 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<SkSpecialImage> rasterImage(SkSpecialImage::MakeFromRaster( + nullptr, + SkIRect::MakeWH(kFullSize, + kFullSize), + bm)); + + { + sk_sp<SkSpecialImage> fromRaster(rasterImage->makeTextureImage(nullptr, context)); + test_texture_backed(reporter, rasterImage, fromRaster); + } + + { + sk_sp<SkSpecialImage> subRasterImage(rasterImage->makeSubset(subset)); + + sk_sp<SkSpecialImage> 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<GrTexture> texture(context->textureProvider()->createTexture(desc, + SkBudgeted::kNo, + bm.getPixels(), + 0)); + if (!texture) { + return; + } + + sk_sp<SkSpecialImage> gpuImage(SkSpecialImage::MakeFromGpu( + nullptr, + SkIRect::MakeWH(kFullSize, + kFullSize), + kNeedNewImageUniqueID_SpecialImage, + texture)); + + { + sk_sp<SkSpecialImage> fromGPU(gpuImage->makeTextureImage(nullptr, context)); + test_texture_backed(reporter, gpuImage, fromGPU); + } + + { + sk_sp<SkSpecialImage> subGPUImage(gpuImage->makeSubset(subset)); + + sk_sp<SkSpecialImage> 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<GrTexture> texture(context->textureProvider()->createTexture(desc, SkBudgeted::kNo, + SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc, + SkBudgeted::kNo, bm.getPixels(), 0)); if (!texture) { return; |