aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-06-29 07:37:01 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-06-29 07:37:01 -0700
commitfa5e68e4b4a10227d3e2c0725b55260175903a80 (patch)
treec6171685792b29e70a1912b280f758013d855a9b
parente784db417d72ce08828c572ed107e91222e0c0f1 (diff)
add getTextureHandle to SkSurface
-rw-r--r--include/core/SkSurface.h16
-rw-r--r--src/image/SkSurface.cpp4
-rw-r--r--src/image/SkSurface_Base.h4
-rw-r--r--src/image/SkSurface_Gpu.cpp18
-rw-r--r--src/image/SkSurface_Gpu.h1
-rw-r--r--tests/SurfaceTest.cpp31
6 files changed, 72 insertions, 2 deletions
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index 8ccfa31124..5d08ee67d3 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -138,9 +138,25 @@ public:
/**
* Call this if the contents are about to change. This will (lazily) force a new
* value to be returned from generationID() when it is called next.
+ *
+ * CAN WE DEPRECATE THIS?
*/
void notifyContentWillChange(ContentChangeMode mode);
+ enum TextureHandleAccess {
+ kFlushRead_TextureHandleAccess, //!< caller may read from the texture
+ kFlushWrite_TextureHandleAccess, //!< caller may write to the texture
+ kDiscardWrite_TextureHandleAccess, //!< caller must over-write the entire texture
+ };
+ /**
+ * Retrieves the backend API handle of the texture used by this surface, or 0 if the surface
+ * is not backed by a GPU texture.
+ *
+ * The returned texture-handle is only valid until the next draw-call into the surface,
+ * or the surface is deleted.
+ */
+ GrBackendObject getTextureHandle(TextureHandleAccess);
+
/**
* Return a canvas that will draw into this surface. This will always
* return the same canvas for a given surface, and is manged/owned by the
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index a99997306b..34035a3670 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -175,6 +175,10 @@ bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t d
return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
}
+GrBackendObject SkSurface::getTextureHandle(TextureHandleAccess access) {
+ return asSB(this)->onGetTextureHandle(access);
+}
+
//////////////////////////////////////////////////////////////////////////////////////
#if !SK_SUPPORT_GPU
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index 30af9761d3..3f1301ee34 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -18,6 +18,10 @@ public:
SkSurface_Base(const SkImageInfo&, const SkSurfaceProps*);
virtual ~SkSurface_Base();
+ virtual GrBackendObject onGetTextureHandle(TextureHandleAccess) {
+ return 0;
+ }
+
/**
* Allocate a canvas that will draw into this surface. We will cache this
* canvas, to return the same object to the caller multiple times. We
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index fa006a61cd..34532f7cb9 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -26,6 +26,24 @@ SkSurface_Gpu::~SkSurface_Gpu() {
fDevice->unref();
}
+GrBackendObject SkSurface_Gpu::onGetTextureHandle(TextureHandleAccess access) {
+ GrRenderTarget* rt = fDevice->accessRenderTarget();
+ switch (access) {
+ case kFlushRead_TextureHandleAccess:
+ rt->prepareForExternalRead(); // todo: rename to prepareForExternalAccess()
+ break;
+ case kFlushWrite_TextureHandleAccess:
+ this->notifyContentWillChange(kRetain_ContentChangeMode);
+ rt->flushWrites();
+ break;
+ case kDiscardWrite_TextureHandleAccess:
+ this->notifyContentWillChange(kDiscard_ContentChangeMode);
+ rt->discard();
+ break;
+ }
+ return rt->asTexture()->getTextureHandle();
+}
+
SkCanvas* SkSurface_Gpu::onNewCanvas() {
SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags;
// When we think this works...
diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h
index 025cb7d8e2..ed94a24fcd 100644
--- a/src/image/SkSurface_Gpu.h
+++ b/src/image/SkSurface_Gpu.h
@@ -21,6 +21,7 @@ public:
SkSurface_Gpu(SkGpuDevice*);
virtual ~SkSurface_Gpu();
+ GrBackendObject onGetTextureHandle(TextureHandleAccess) override;
SkCanvas* onNewCanvas() override;
SkSurface* onNewSurface(const SkImageInfo&) override;
SkImage* onNewImageSnapshot(Budgeted) override;
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index c45e94e883..817906070a 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -223,7 +223,30 @@ struct ReleaseDataContext {
}
};
-static SkImage* create_image(ImageType imageType, GrContext* context, SkColor color,
+static void test_texture_handle(skiatest::Reporter* reporter, SkSurface* surf) {
+ SkAutoTUnref<SkImage> image0(surf->newImageSnapshot());
+ GrBackendObject obj = surf->getTextureHandle(SkSurface::kFlushRead_TextureHandleAccess);
+ REPORTER_ASSERT(reporter, obj != 0);
+ SkAutoTUnref<SkImage> image1(surf->newImageSnapshot());
+ // just read access should not affect the snapshot
+ REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
+
+ obj = surf->getTextureHandle(SkSurface::kFlushWrite_TextureHandleAccess);
+ REPORTER_ASSERT(reporter, obj != 0);
+ SkAutoTUnref<SkImage> image2(surf->newImageSnapshot());
+ // expect a new image, since we claimed we would write
+ REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
+
+ obj = surf->getTextureHandle(SkSurface::kDiscardWrite_TextureHandleAccess);
+ REPORTER_ASSERT(reporter, obj != 0);
+ SkAutoTUnref<SkImage> image3(surf->newImageSnapshot());
+ // expect a new(er) image, since we claimed we would write
+ REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
+ REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
+}
+
+static SkImage* create_image(skiatest::Reporter* reporter,
+ ImageType imageType, GrContext* context, SkColor color,
ReleaseDataContext* releaseContext) {
const SkPMColor pmcolor = SkPreMultiplyColor(color);
const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
@@ -248,6 +271,10 @@ static SkImage* create_image(ImageType imageType, GrContext* context, SkColor co
SkAutoTUnref<SkSurface> surf(
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0));
surf->getCanvas()->clear(color);
+ // test our backing texture while were here...
+ test_texture_handle(reporter, surf);
+ // redraw so our returned image looks as expected.
+ surf->getCanvas()->clear(color);
return surf->newImageSnapshot();
}
case kCodec_ImageType: {
@@ -351,7 +378,7 @@ static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto
size_t rowBytes;
releaseCtx.fData = NULL;
- SkAutoTUnref<SkImage> image(create_image(gRec[i].fType, ctx, color, &releaseCtx));
+ SkAutoTUnref<SkImage> image(create_image(reporter, gRec[i].fType, ctx, color, &releaseCtx));
if (!image.get()) {
SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName);
continue; // gpu may not be enabled