From fa5e68e4b4a10227d3e2c0725b55260175903a80 Mon Sep 17 00:00:00 2001 From: reed Date: Mon, 29 Jun 2015 07:37:01 -0700 Subject: add getTextureHandle to SkSurface BUG=485243 Review URL: https://codereview.chromium.org/1210303003 --- include/core/SkSurface.h | 16 ++++++++++++++++ src/image/SkSurface.cpp | 4 ++++ src/image/SkSurface_Base.h | 4 ++++ src/image/SkSurface_Gpu.cpp | 18 ++++++++++++++++++ src/image/SkSurface_Gpu.h | 1 + tests/SurfaceTest.cpp | 31 +++++++++++++++++++++++++++++-- 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 image0(surf->newImageSnapshot()); + GrBackendObject obj = surf->getTextureHandle(SkSurface::kFlushRead_TextureHandleAccess); + REPORTER_ASSERT(reporter, obj != 0); + SkAutoTUnref 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 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 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 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 image(create_image(gRec[i].fType, ctx, color, &releaseCtx)); + SkAutoTUnref 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 -- cgit v1.2.3