aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2016-03-18 08:14:27 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-18 08:14:27 -0700
commit83c17fa56b23159166394cb3feb431ffafbbab48 (patch)
tree5a13d5597db58b5baccd2ac599706e1c4f24a8bd
parent2b1b40e11afc41452b4d2f74cdebb1b6e6f7cc96 (diff)
Add SkSpecialImage::makeTextureImage entry point
-rw-r--r--src/core/SkImageFilter.cpp13
-rw-r--r--src/core/SkSpecialImage.cpp40
-rw-r--r--src/core/SkSpecialImage.h11
-rw-r--r--tests/SpecialImageTest.cpp78
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;