From f865b05fe50ca2c094b9c60e4405c6094415b4f6 Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Fri, 9 Mar 2018 09:01:53 -0500 Subject: Add GM configs that test rendering to a GL backend texture and render target This also adds GrGpu::create/deleteTestingOnlyBackendRenderTarget. Implemented in GL only for now. Change-Id: I9e5fdc953c4a249959af89e08332f520cefe9d90 Reviewed-on: https://skia-review.googlesource.com/113305 Reviewed-by: Greg Daniel Commit-Queue: Brian Salomon --- src/gpu/GrGpu.h | 20 +++++++----- src/gpu/gl/GrGLGpu.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++-- src/gpu/gl/GrGLGpu.h | 16 ++++++---- src/gpu/mock/GrMockGpu.cpp | 9 ++++++ src/gpu/mock/GrMockGpu.h | 6 ++++ src/gpu/mtl/GrMtlGpu.h | 8 +++++ src/gpu/vk/GrVkGpu.cpp | 10 ++++++ src/gpu/vk/GrVkGpu.h | 6 ++++ 8 files changed, 138 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 0c794e2eff..d63a38b758 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -448,12 +448,12 @@ public: Stats* stats() { return &fStats; } void dumpJSON(SkJSONWriter*) const; +#if GR_TEST_UTILS /** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is only to be used for testing (particularly for testing the methods that import an externally created texture into Skia. Must be matched with a call to deleteTestingOnlyTexture(). */ GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, SkColorType, bool isRenderTarget, GrMipMapped); - /** Older version based on GrPixelConfig. Currently the preferred one above devolves to this. */ virtual GrBackendTexture createTestingOnlyBackendTexture( void* pixels, int w, int h, @@ -468,11 +468,23 @@ public: */ virtual void deleteTestingOnlyBackendTexture(GrBackendTexture*) = 0; + virtual GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType, + GrSRGBEncoded) = 0; + + virtual void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) = 0; + + // This is only to be used in GL-specific tests. + virtual const GrGLContext* glContextForTesting() const { return nullptr; } + + // This is only to be used by testing code + virtual void resetShaderCacheForTesting() const {} + /** * Flushes all work to the gpu and forces the GPU to wait until all the gpu work has completed. * This is for testing purposes only. */ virtual void testingOnly_flushGpuAndSync() = 0; +#endif // width and height may be larger than rt (if underlying API allows it). // Returns nullptr if compatible sb could not be created, otherwise the caller owns the ref on @@ -504,12 +516,6 @@ public: return this->onIsACopyNeededForTextureParams(proxy, params, copyParams, scaleAdjust); } - // This is only to be used in GL-specific tests. - virtual const GrGLContext* glContextForTesting() const { return nullptr; } - - // This is only to be used by testing code - virtual void resetShaderCacheForTesting() const {} - void handleDirtyContext() { if (fResetBits) { this->resetContext(); diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 82be0d1a97..7499e761c9 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -4344,6 +4344,7 @@ void GrGLGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType type) { } } +#if GR_TEST_UTILS GrBackendTexture GrGLGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig config, bool /*isRT*/, GrMipMapped mipMapped) { @@ -4434,13 +4435,86 @@ void GrGLGpu::deleteTestingOnlyBackendTexture(GrBackendTexture* tex) { } } -void GrGLGpu::resetShaderCacheForTesting() const { - fProgramCache->abandon(); +GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h, + GrColorType colorType, + GrSRGBEncoded srgbEncoded) { + auto config = GrColorTypeToPixelConfig(colorType, srgbEncoded); + GrGLenum colorBufferFormat; + if (!this->glCaps().getRenderbufferFormat(config, &colorBufferFormat)) { + return {}; + } + int sFormatIdx = this->getCompatibleStencilIndex(config); + if (sFormatIdx < 0) { + return {}; + } + GrGLuint rbIDs[] = {0, 0}; + GL_CALL(GenRenderbuffers(2, rbIDs)); + if (!rbIDs[0] || !rbIDs[1]) { + if (!rbIDs[0]) { + GL_CALL(DeleteRenderbuffers(1, &rbIDs[0])); + } + if (!rbIDs[1]) { + GL_CALL(DeleteRenderbuffers(1, &rbIDs[1])); + } + return {}; + } + GrGLFramebufferInfo info; + info.fFBOID = 0; + GL_CALL(GenFramebuffers(1, &info.fFBOID)); + if (!info.fFBOID) { + GL_CALL(DeleteRenderbuffers(2, rbIDs)); + return GrBackendRenderTarget(); + } + + this->invalidateBoundRenderTarget(); + + GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID)); + GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbIDs[0])); + GL_ALLOC_CALL(this->glInterface(), + RenderbufferStorage(GR_GL_RENDERBUFFER, colorBufferFormat, w, h)); + GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_RENDERBUFFER, + rbIDs[0])); + GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbIDs[1])); + auto stencilBufferFormat = this->glCaps().stencilFormats()[sFormatIdx].fInternalFormat; + GL_ALLOC_CALL(this->glInterface(), + RenderbufferStorage(GR_GL_RENDERBUFFER, stencilBufferFormat, w, h)); + GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_STENCIL_ATTACHMENT, GR_GL_RENDERBUFFER, + rbIDs[1])); + if (this->glCaps().stencilFormats()[sFormatIdx].fPacked) { + GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT, + GR_GL_RENDERBUFFER, rbIDs[1])); + } + + // We don't want to have to recover the renderbuffer IDs later to delete them. OpenGL has this + // rule that if a renderbuffer is deleted and a FBO other than the current FBO has the RB + // attached then deletion is delayed. So we unbind the FBO here and delete the renderbuffers. + GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); + GL_CALL(DeleteRenderbuffers(2, rbIDs)); + + GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID)); + GrGLenum status; + GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); + if (GR_GL_FRAMEBUFFER_COMPLETE != status) { + GL_CALL(DeleteFramebuffers(1, &info.fFBOID)); + return {}; + } + auto stencilBits = SkToInt(this->glCaps().stencilFormats()[sFormatIdx].fStencilBits); + return {w, h, 1, stencilBits, config, info}; +} + +void GrGLGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& backendRT) { + SkASSERT(kOpenGL_GrBackend == backendRT.backend()); + if (auto info = backendRT.getGLFramebufferInfo()) { + if (info->fFBOID) { + GL_CALL(DeleteFramebuffers(1, &info->fFBOID)); + } + } } void GrGLGpu::testingOnly_flushGpuAndSync() { GL_CALL(Finish()); } +#endif /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 3a67958d5f..fa3d9e09c7 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -128,10 +128,6 @@ public: void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*, GrSurfaceOrigin); - const GrGLContext* glContextForTesting() const override { - return &this->glContext(); - } - void clearStencil(GrRenderTarget*, int clearValue) override; GrGpuRTCommandBuffer* createCommandBuffer( @@ -148,7 +144,7 @@ public: GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget* rt, int width, int height) override; - +#if GR_TEST_UTILS GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig config, bool isRenderTarget, @@ -156,9 +152,17 @@ public: bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override; void deleteTestingOnlyBackendTexture(GrBackendTexture*) override; - void resetShaderCacheForTesting() const override; + GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType, + GrSRGBEncoded) override; + + void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override; + + const GrGLContext* glContextForTesting() const override { return &this->glContext(); } + + void resetShaderCacheForTesting() const override { fProgramCache->abandon(); } void testingOnly_flushGpuAndSync() override; +#endif GrFence SK_WARN_UNUSED_RESULT insertFence() override; bool waitFence(GrFence, uint64_t timeout) override; diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp index e31a775730..50b19f15e9 100644 --- a/src/gpu/mock/GrMockGpu.cpp +++ b/src/gpu/mock/GrMockGpu.cpp @@ -107,6 +107,7 @@ GrStencilAttachment* GrMockGpu::createStencilAttachmentForRenderTarget(const GrR return new GrMockStencilAttachment(this, width, height, kBits, rt->numColorSamples()); } +#if GR_TEST_UTILS GrBackendTexture GrMockGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig config, bool isRT, GrMipMapped) { @@ -136,3 +137,11 @@ void GrMockGpu::deleteTestingOnlyBackendTexture(GrBackendTexture* tex) { fOutstandingTestingOnlyTextureIDs.remove(info->fID); } } + +GrBackendRenderTarget GrMockGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType, + GrSRGBEncoded) { + return {}; +} + +void GrMockGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {} +#endif diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h index 00b19ac82e..b58b9ff6d7 100644 --- a/src/gpu/mock/GrMockGpu.h +++ b/src/gpu/mock/GrMockGpu.h @@ -119,12 +119,18 @@ private: int height) override; void clearStencil(GrRenderTarget*, int clearValue) override {} +#if GR_TEST_UTILS GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig, bool isRT, GrMipMapped) override; bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override; void deleteTestingOnlyBackendTexture(GrBackendTexture*) override; + GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType, + GrSRGBEncoded) override; + void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override; + void testingOnly_flushGpuAndSync() override {} +#endif static int NextInternalTextureID(); static int NextExternalTextureID(); diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h index 9907e95d29..38b4e6303c 100644 --- a/src/gpu/mtl/GrMtlGpu.h +++ b/src/gpu/mtl/GrMtlGpu.h @@ -137,6 +137,7 @@ private: void clearStencil(GrRenderTarget* target, int clearValue) override {} +#if GR_TEST_UTILS GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig config, bool isRT, GrMipMapped) override { @@ -145,7 +146,14 @@ private: bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override { return false; } void deleteTestingOnlyBackendTexture(GrBackendTexture*) override {} + GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType, + GrSRGBEncoded) override { + return {}; + } + void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override {} + void testingOnly_flushGpuAndSync() override {} +#endif sk_sp fMtlCaps; diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index b6268a7a65..b674185a00 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -1181,6 +1181,7 @@ bool copy_testing_data(GrVkGpu* gpu, void* srcData, const GrVkAlloc& alloc, size return true; } +#if GR_TEST_UTILS GrBackendTexture GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h, GrPixelConfig config, bool isRenderTarget, @@ -1509,9 +1510,18 @@ void GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendTexture* tex) { } } +GrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType, + GrSRGBEncoded) { + return GrBackendRenderTarget(); +} + +void GrVkGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {} + + void GrVkGpu::testingOnly_flushGpuAndSync() { this->submitCommandBuffer(kForce_SyncQueue); } +#endif //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index 4d1685eb29..81517af86e 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -69,6 +69,7 @@ public: void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {} +#if GR_TEST_UTILS GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig config, bool isRenderTarget, @@ -76,7 +77,12 @@ public: bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override; void deleteTestingOnlyBackendTexture(GrBackendTexture*) override; + GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType, + GrSRGBEncoded) override; + void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override; + void testingOnly_flushGpuAndSync() override; +#endif GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*, int width, -- cgit v1.2.3