Add GrBackendTexture/RenderTarget accessors to SkSurface

Change-Id: I63477fd4b8d48dc50af72736f0f8df566cd96d4a
Reviewed-on: https://skia-review.googlesource.com/85220
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Cary Clark <caryclark@skia.org>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2018-04-05 09:30:38 -04:00 committed by Skia Commit-Bot
parent 91749c8252
commit 8caf85f9f4
14 changed files with 265 additions and 74 deletions

View File

@ -1089,6 +1089,56 @@ In OpenGL this returns the frame buffer object ID.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
#Method GrBackendTexture getBackendTexture(BackendHandleAccess backendHandleAccess)
#In Property
#Line # returns the GPU reference to texture ##
Retrieves the backend texture. If Surface has no backend texture, an invalid
object is returned. Call GrBackendTexture::isValid to determine if the result
is valid.
The returned GrBackendTexture should be discarded if the Surface is drawn to or deleted.
#Param backendHandleAccess one of: kFlushRead_BackendHandleAccess,
kFlushWrite_BackendHandleAccess, kDiscardWrite_BackendHandleAccess
##
#Return GPU texture reference; invalid on failure ##
#NoExample
##
#SeeAlso GrBackendTexture BackendHandleAccess getBackendRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method GrBackendRenderTarget getBackendRenderTarget(BackendHandleAccess backendHandleAccess)
#In Property
#Line # returns the GPU reference to render target ##
Retrieves the backend render target. If Surface has no backend render target, an invalid
object is returned. Call GrBackendRenderTarget::isValid to determine if the result
is valid.
The returned GrBackendRenderTarget should be discarded if the Surface is drawn to
or deleted.
#Param backendHandleAccess one of: kFlushRead_BackendHandleAccess,
kFlushWrite_BackendHandleAccess, kDiscardWrite_BackendHandleAccess
##
#Return GPU render target reference; invalid on failure ##
#NoExample
##
#SeeAlso GrBackendRenderTarget BackendHandleAccess getBackendTexture
#Method ##
# ------------------------------------------------------------------------------
#Method SkCanvas* getCanvas() #Method SkCanvas* getCanvas()
#In Property #In Property
#Line # returns Canvas that draws into Surface ## #Line # returns Canvas that draws into Surface ##

View File

@ -713,6 +713,13 @@ FT_Load_Glyph
## ##
## ##
#Topic RenderTarget
#Class GrBackendRenderTarget
#Method bool isValid() const
##
##
##
#Topic Transfer_Mode #Topic Transfer_Mode
## ##

View File

@ -20,6 +20,7 @@ class SkPaint;
class SkSurfaceCharacterization; class SkSurfaceCharacterization;
class GrBackendRenderTarget; class GrBackendRenderTarget;
class GrBackendSemaphore; class GrBackendSemaphore;
class GrBackendTexture;
class GrContext; class GrContext;
class GrRenderTarget; class GrRenderTarget;
@ -458,6 +459,35 @@ public:
bool getRenderTargetHandle(GrBackendObject* backendObject, bool getRenderTargetHandle(GrBackendObject* backendObject,
BackendHandleAccess backendHandleAccess); BackendHandleAccess backendHandleAccess);
#if GR_TEST_UTILS
/** Retrieves the backend texture. If Surface has no backend texture, an invalid
object is returned. Call GrBackendTexture::isValid to determine if the result
is valid.
The returned GrBackendTexture should be discarded if the Surface is drawn to or deleted.
@param backendHandleAccess one of: kFlushRead_BackendHandleAccess,
kFlushWrite_BackendHandleAccess,
kDiscardWrite_BackendHandleAccess
@return GPU texture reference; invalid on failure
*/
GrBackendTexture getBackendTexture(BackendHandleAccess backendHandleAccess);
/** Retrieves the backend render target. If Surface has no backend render target, an invalid
object is returned. Call GrBackendRenderTarget::isValid to determine if the result
is valid.
The returned GrBackendRenderTarget should be discarded if the Surface is drawn to
or deleted.
@param backendHandleAccess one of: kFlushRead_BackendHandleAccess,
kFlushWrite_BackendHandleAccess,
kDiscardWrite_BackendHandleAccess
@return GPU render target reference; invalid on failure
*/
GrBackendRenderTarget getBackendRenderTarget(BackendHandleAccess backendHandleAccess);
#endif
/** Returns SkCanvas that draws into SkSurface. Subsequent calls return the same SkCanvas. /** Returns SkCanvas that draws into SkSurface. Subsequent calls return the same SkCanvas.
SkCanvas returned is managed and owned by SkSurface, and is deleted when SkSurface SkCanvas returned is managed and owned by SkSurface, and is deleted when SkSurface
is deleted. is deleted.

View File

@ -16,6 +16,24 @@
#include "vk/GrVkTypes.h" #include "vk/GrVkTypes.h"
#endif #endif
#if !SK_SUPPORT_GPU
// SkSurface and SkImage rely on a minimal version of these always being available
class SK_API GrBackendTexture {
public:
GrBackendTexture() {}
bool isValid() const { return false; }
};
class SK_API GrBackendRenderTarget {
public:
GrBackendRenderTarget() {}
bool isValid() const { return false; }
};
#else
class SK_API GrBackendFormat { class SK_API GrBackendFormat {
public: public:
// Creates an invalid backend format. // Creates an invalid backend format.
@ -239,7 +257,11 @@ public:
// Returns true if the backend texture has been initialized. // Returns true if the backend texture has been initialized.
bool isValid() const { return fConfig != kUnknown_GrPixelConfig; } bool isValid() const { return fConfig != kUnknown_GrPixelConfig; }
#if GR_TEST_UTILS
GrPixelConfig testingOnly_getPixelConfig() const; GrPixelConfig testingOnly_getPixelConfig() const;
static bool TestingOnly_Equals(const GrBackendRenderTarget&, const GrBackendRenderTarget&);
#endif
private: private:
// Friending for access to the GrPixelConfig // Friending for access to the GrPixelConfig
@ -272,3 +294,5 @@ private:
#endif #endif
#endif

View File

@ -124,6 +124,10 @@ GR_STATIC_ASSERT(sizeof(GrBackendObject) >= sizeof(const GrGLTextureInfo*));
struct GrGLFramebufferInfo { struct GrGLFramebufferInfo {
GrGLuint fFBOID; GrGLuint fFBOID;
GrGLenum fFormat = 0; GrGLenum fFormat = 0;
bool operator==(const GrGLFramebufferInfo& that) const {
return fFBOID == that.fFBOID && fFormat == that.fFormat;
}
}; };
GR_STATIC_ASSERT(sizeof(GrBackendObject) >= sizeof(const GrGLFramebufferInfo*)); GR_STATIC_ASSERT(sizeof(GrBackendObject) >= sizeof(const GrGLFramebufferInfo*));

View File

@ -290,3 +290,40 @@ const GrMockRenderTargetInfo* GrBackendRenderTarget::getMockRenderTargetInfo() c
} }
return nullptr; return nullptr;
} }
#if GR_TEST_UTILS
bool GrBackendRenderTarget::TestingOnly_Equals(const GrBackendRenderTarget& r0,
const GrBackendRenderTarget& r1) {
if (!r0.isValid() || !r1.isValid()) {
return false; // two invalid backend rendertargets are not considered equal
}
if (r0.fWidth != r1.fWidth ||
r0.fHeight != r1.fHeight ||
r0.fSampleCnt != r1.fSampleCnt ||
r0.fStencilBits != r1.fStencilBits ||
r0.fConfig != r1.fConfig ||
r0.fBackend != r1.fBackend) {
return false;
}
switch (r0.fBackend) {
case kOpenGL_GrBackend:
return r0.fGLInfo == r1.fGLInfo;
case kMock_GrBackend:
return r0.fMockInfo == r1.fMockInfo;
case kVulkan_GrBackend:
#ifdef SK_VULKAN
return r0.fVkInfo == r1.fVkInfo;
#else
// fall through
#endif
case kMetal_GrBackend: // fall through
default:
return false;
}
SkASSERT(0);
return false;
}
#endif

View File

@ -29,6 +29,7 @@
#include "GrContext.h" #include "GrContext.h"
#include "SkImage_Gpu.h" #include "SkImage_Gpu.h"
#endif #endif
#include "GrBackendSurface.h"
SkImage::SkImage(int width, int height, uint32_t uniqueID) SkImage::SkImage(int width, int height, uint32_t uniqueID)
: fWidth(width) : fWidth(width)
@ -218,6 +219,11 @@ SkImage_Base::~SkImage_Base() {
} }
} }
GrBackendTexture SkImage_Base::onGetBackendTexture(bool flushPendingGrContextIO,
GrSurfaceOrigin* origin) const {
return GrBackendTexture(); // invalid
}
bool SkImage::readPixels(const SkPixmap& pmap, int srcX, int srcY, CachingHint chint) const { bool SkImage::readPixels(const SkPixmap& pmap, int srcX, int srcY, CachingHint chint) const {
return this->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), srcX, srcY, chint); return this->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), srcX, srcY, chint);
} }

View File

@ -13,17 +13,9 @@
#include "SkSurface.h" #include "SkSurface.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrBackendSurface.h"
#include "GrTextureProxy.h" #include "GrTextureProxy.h"
class GrTexture; class GrTexture;
#else
class SK_API GrBackendTexture {
public:
GrBackendTexture() {}
bool isValid() const { return false; }
};
#endif #endif
#include <new> #include <new>
@ -67,13 +59,12 @@ public:
GrSurfaceOrigin* origin) const { GrSurfaceOrigin* origin) const {
return 0; return 0;
} }
virtual GrBackendTexture onGetBackendTexture(bool flushPendingGrContextIO,
GrSurfaceOrigin* origin) const {
return GrBackendTexture(); // invalid
}
virtual GrTexture* onGetTexture() const { return nullptr; } virtual GrTexture* onGetTexture() const { return nullptr; }
#endif #endif
virtual GrBackendTexture onGetBackendTexture(bool flushPendingGrContextIO,
GrSurfaceOrigin* origin) const;
virtual SkImageCacherator* peekCacherator() const { return nullptr; } virtual SkImageCacherator* peekCacherator() const { return nullptr; }
// return a read-only copy of the pixels. We promise to not modify them, // return a read-only copy of the pixels. We promise to not modify them,

View File

@ -6,11 +6,13 @@
*/ */
#include "SkAtomics.h" #include "SkAtomics.h"
#include "SkSurface_Base.h"
#include "SkImagePriv.h"
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkFontLCDConfig.h" #include "SkFontLCDConfig.h"
#include "SkImagePriv.h"
#include "SkSurface_Base.h"
#include "GrBackendSurface.h"
static SkPixelGeometry compute_default_geometry() { static SkPixelGeometry compute_default_geometry() {
SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder(); SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
if (SkFontLCDConfig::kNONE_LCDOrder == order) { if (SkFontLCDConfig::kNONE_LCDOrder == order) {
@ -70,6 +72,14 @@ SkSurface_Base::~SkSurface_Base() {
} }
} }
GrBackendTexture SkSurface_Base::onGetBackendTexture(BackendHandleAccess) {
return GrBackendTexture(); // invalid
}
GrBackendRenderTarget SkSurface_Base::onGetBackendRenderTarget(BackendHandleAccess) {
return GrBackendRenderTarget(); // invalid
}
void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) { void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
auto image = this->makeImageSnapshot(); auto image = this->makeImageSnapshot();
if (image) { if (image) {
@ -216,6 +226,16 @@ bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess
return asSB(this)->onGetRenderTargetHandle(obj, access); return asSB(this)->onGetRenderTargetHandle(obj, access);
} }
#if GR_TEST_UTILS
GrBackendTexture SkSurface::getBackendTexture(BackendHandleAccess access) {
return asSB(this)->onGetBackendTexture(access);
}
GrBackendRenderTarget SkSurface::getBackendRenderTarget(BackendHandleAccess access) {
return asSB(this)->onGetBackendRenderTarget(access);
}
#endif
void SkSurface::prepareForExternalIO() { void SkSurface::prepareForExternalIO() {
this->flush(); this->flush();
} }

View File

@ -27,6 +27,9 @@ public:
return false; return false;
} }
virtual GrBackendTexture onGetBackendTexture(BackendHandleAccess);
virtual GrBackendRenderTarget onGetBackendRenderTarget(BackendHandleAccess);
/** /**
* Allocate a canvas that will draw into this surface. We will cache this * 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 * canvas, to return the same object to the caller multiple times. We

View File

@ -72,6 +72,27 @@ bool SkSurface_Gpu::onGetRenderTargetHandle(GrBackendObject* obj, BackendHandleA
return true; return true;
} }
GrBackendTexture SkSurface_Gpu::onGetBackendTexture(BackendHandleAccess access) {
GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
if (!rt) {
return GrBackendTexture(); // invalid
}
GrTexture* texture = rt->asTexture();
if (texture) {
return texture->getBackendTexture();
}
return GrBackendTexture(); // invalid
}
GrBackendRenderTarget SkSurface_Gpu::onGetBackendRenderTarget(BackendHandleAccess access) {
GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
if (!rt) {
return GrBackendRenderTarget(); // invalid
}
return rt->getBackendRenderTarget();
}
SkCanvas* SkSurface_Gpu::onNewCanvas() { SkCanvas* SkSurface_Gpu::onNewCanvas() {
SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags; SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags;
flags = static_cast<SkCanvas::InitFlags>(flags | SkCanvas::kConservativeRasterClip_InitFlag); flags = static_cast<SkCanvas::InitFlags>(flags | SkCanvas::kConservativeRasterClip_InitFlag);

View File

@ -25,6 +25,10 @@ public:
GrBackendObject onGetTextureHandle(BackendHandleAccess) override; GrBackendObject onGetTextureHandle(BackendHandleAccess) override;
bool onGetRenderTargetHandle(GrBackendObject*, BackendHandleAccess) override; bool onGetRenderTargetHandle(GrBackendObject*, BackendHandleAccess) override;
GrBackendTexture onGetBackendTexture(BackendHandleAccess) override;
GrBackendRenderTarget onGetBackendRenderTarget(BackendHandleAccess) override;
SkCanvas* onNewCanvas() override; SkCanvas* onNewCanvas() override;
sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override; sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
sk_sp<SkImage> onNewImageSnapshot() override; sk_sp<SkImage> onNewImageSnapshot() override;

View File

@ -16,6 +16,7 @@
#include "Test.h" #include "Test.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrBackendSurface.h"
#include "GrContext.h" #include "GrContext.h"
#include "GrContextPriv.h" #include "GrContextPriv.h"
#include "GrProxyProvider.h" #include "GrProxyProvider.h"
@ -126,17 +127,20 @@ static void test_image(const sk_sp<SkSpecialImage>& img, skiatest::Reporter* rep
SkPixmap tmpPixmap; SkPixmap tmpPixmap;
REPORTER_ASSERT(reporter, isGPUBacked != !!tightImg->peekPixels(&tmpPixmap)); REPORTER_ASSERT(reporter, isGPUBacked != !!tightImg->peekPixels(&tmpPixmap));
} }
#if SK_SUPPORT_GPU
{ {
SkImageFilter::OutputProperties outProps(img->getColorSpace()); SkImageFilter::OutputProperties outProps(img->getColorSpace());
sk_sp<SkSurface> tightSurf(img->makeTightSurface(outProps, subset.size())); sk_sp<SkSurface> tightSurf(img->makeTightSurface(outProps, subset.size()));
REPORTER_ASSERT(reporter, tightSurf->width() == subset.width()); REPORTER_ASSERT(reporter, tightSurf->width() == subset.width());
REPORTER_ASSERT(reporter, tightSurf->height() == subset.height()); REPORTER_ASSERT(reporter, tightSurf->height() == subset.height());
REPORTER_ASSERT(reporter, isGPUBacked == GrBackendTexture backendTex = tightSurf->getBackendTexture(
!!tightSurf->getTextureHandle(SkSurface::kDiscardWrite_BackendHandleAccess)); SkSurface::kDiscardWrite_BackendHandleAccess);
REPORTER_ASSERT(reporter, isGPUBacked == backendTex.isValid());
SkPixmap tmpPixmap; SkPixmap tmpPixmap;
REPORTER_ASSERT(reporter, isGPUBacked != !!tightSurf->peekPixels(&tmpPixmap)); REPORTER_ASSERT(reporter, isGPUBacked != !!tightSurf->peekPixels(&tmpPixmap));
} }
#endif
} }
DEF_TEST(SpecialImage_Raster, reporter) { DEF_TEST(SpecialImage_Raster, reporter) {

View File

@ -285,62 +285,48 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu, reporter, ctxIn
} }
} }
} }
#endif
static GrBackendObject get_surface_backend_texture_handle( static void test_backend_texture_access_copy_on_write(
SkSurface* s, SkSurface::BackendHandleAccess a) { skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess access) {
return s->getTextureHandle(a); GrBackendTexture tex1 = surface->getBackendTexture(access);
}
static GrBackendObject get_surface_backend_render_target_handle(
SkSurface* s, SkSurface::BackendHandleAccess a) {
GrBackendObject result;
if (!s->getRenderTargetHandle(&result, a)) {
return 0;
}
return result;
}
static void test_backend_handle_access_copy_on_write(
skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess mode,
GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
GrBackendObject obj1 = func(surface, mode);
sk_sp<SkImage> snap1(surface->makeImageSnapshot()); sk_sp<SkImage> snap1(surface->makeImageSnapshot());
GrBackendObject obj2 = func(surface, mode); GrBackendTexture tex2 = surface->getBackendTexture(access);
sk_sp<SkImage> snap2(surface->makeImageSnapshot()); sk_sp<SkImage> snap2(surface->makeImageSnapshot());
// If the access mode triggers CoW, then the backend objects should reflect it. // If the access mode triggers CoW, then the backend objects should reflect it.
REPORTER_ASSERT(reporter, (obj1 == obj2) == (snap1 == snap2)); REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(tex1, tex2) == (snap1 == snap2));
} }
DEF_TEST(SurfaceBackendHandleAccessCopyOnWrite, reporter) {
const SkSurface::BackendHandleAccess accessModes[] = { static void test_backend_rendertarget_access_copy_on_write(
SkSurface::kFlushRead_BackendHandleAccess, skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess access) {
SkSurface::kFlushWrite_BackendHandleAccess, GrBackendRenderTarget rt1 = surface->getBackendRenderTarget(access);
SkSurface::kDiscardWrite_BackendHandleAccess, sk_sp<SkImage> snap1(surface->makeImageSnapshot());
};
for (auto& handle_access_func : GrBackendRenderTarget rt2 = surface->getBackendRenderTarget(access);
{ &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) { sk_sp<SkImage> snap2(surface->makeImageSnapshot());
for (auto& accessMode : accessModes) {
auto surface(create_surface()); // If the access mode triggers CoW, then the backend objects should reflect it.
test_backend_handle_access_copy_on_write(reporter, surface.get(), accessMode, REPORTER_ASSERT(reporter, GrBackendRenderTarget::TestingOnly_Equals(rt1, rt2) ==
handle_access_func); (snap1 == snap2));
} }
}
} DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendSurfaceAccessCopyOnWrite_Gpu, reporter, ctxInfo) {
#if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessCopyOnWrite_Gpu, reporter, ctxInfo) {
const SkSurface::BackendHandleAccess accessModes[] = { const SkSurface::BackendHandleAccess accessModes[] = {
SkSurface::kFlushRead_BackendHandleAccess, SkSurface::kFlushRead_BackendHandleAccess,
SkSurface::kFlushWrite_BackendHandleAccess, SkSurface::kFlushWrite_BackendHandleAccess,
SkSurface::kDiscardWrite_BackendHandleAccess, SkSurface::kDiscardWrite_BackendHandleAccess,
}; };
for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
for (auto& handle_access_func :
{ &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) {
for (auto& accessMode : accessModes) { for (auto& accessMode : accessModes) {
{
auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr)); auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
test_backend_handle_access_copy_on_write(reporter, surface.get(), accessMode, test_backend_texture_access_copy_on_write(reporter, surface.get(), accessMode);
handle_access_func); }
{
auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
test_backend_rendertarget_access_copy_on_write(reporter, surface.get(), accessMode);
} }
} }
} }
@ -349,38 +335,42 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessCopyOnWrite_Gpu, re
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
static void test_backend_handle_unique_id( template<typename Type, Type(SkSurface::*func)(SkSurface::BackendHandleAccess)>
skiatest::Reporter* reporter, SkSurface* surface, static void test_backend_unique_id(skiatest::Reporter* reporter, SkSurface* surface) {
GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
sk_sp<SkImage> image0(surface->makeImageSnapshot()); sk_sp<SkImage> image0(surface->makeImageSnapshot());
GrBackendObject obj = func(surface, SkSurface::kFlushRead_BackendHandleAccess);
REPORTER_ASSERT(reporter, obj != 0); Type obj = (surface->*func)(SkSurface::kFlushRead_BackendHandleAccess);
REPORTER_ASSERT(reporter, obj.isValid());
sk_sp<SkImage> image1(surface->makeImageSnapshot()); sk_sp<SkImage> image1(surface->makeImageSnapshot());
// just read access should not affect the snapshot // just read access should not affect the snapshot
REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID()); REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
obj = func(surface, SkSurface::kFlushWrite_BackendHandleAccess); obj = (surface->*func)(SkSurface::kFlushWrite_BackendHandleAccess);
REPORTER_ASSERT(reporter, obj != 0); REPORTER_ASSERT(reporter, obj.isValid());
sk_sp<SkImage> image2(surface->makeImageSnapshot()); sk_sp<SkImage> image2(surface->makeImageSnapshot());
// expect a new image, since we claimed we would write // expect a new image, since we claimed we would write
REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID()); REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
obj = func(surface, SkSurface::kDiscardWrite_BackendHandleAccess); obj = (surface->*func)(SkSurface::kDiscardWrite_BackendHandleAccess);
REPORTER_ASSERT(reporter, obj != 0); REPORTER_ASSERT(reporter, obj.isValid());
sk_sp<SkImage> image3(surface->makeImageSnapshot()); sk_sp<SkImage> image3(surface->makeImageSnapshot());
// expect a new(er) image, since we claimed we would write // expect a new(er) image, since we claimed we would write
REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID()); REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID()); REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
} }
// No CPU test. // No CPU test.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, ctxInfo) { DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, ctxInfo) {
for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
for (auto& test_func : { &test_backend_handle_unique_id }) { {
for (auto& handle_access_func :
{ &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle}) {
auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr)); auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
test_func(reporter, surface.get(), handle_access_func); test_backend_unique_id<GrBackendTexture, &SkSurface::getBackendTexture>(reporter,
surface.get());
} }
{
auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
test_backend_unique_id<GrBackendRenderTarget, &SkSurface::getBackendRenderTarget>(
reporter, surface.get());
} }
} }
} }