From 28361fad1054d59ed4e6a320c7a8b8782a1487c7 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Fri, 28 Mar 2014 16:08:05 +0000 Subject: Add discard API to SkCanvas, plumb it to glDiscardFramebuffer() BUG=skia:2349 R=robertphillips@google.com, reed@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/211683002 git-svn-id: http://skia.googlecode.com/svn/trunk@13976 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrContext.cpp | 8 ++++++++ src/gpu/GrDrawTarget.cpp | 37 ++++++++++++++++++++----------------- src/gpu/GrDrawTarget.h | 6 ++++++ src/gpu/GrDrawTargetCaps.h | 2 ++ src/gpu/GrInOrderDrawBuffer.cpp | 27 +++++++++++++++++++++++---- src/gpu/GrInOrderDrawBuffer.h | 5 ++++- src/gpu/GrRenderTarget.cpp | 9 +++++++++ src/gpu/gl/GrGLCaps.cpp | 5 +---- src/gpu/gl/GrGLCaps.h | 4 ---- src/gpu/gl/GrGLDefines.h | 5 +++++ src/gpu/gl/GrGpuGL.cpp | 19 +++++++++++++++++++ src/gpu/gl/GrGpuGL.h | 2 ++ 12 files changed, 99 insertions(+), 30 deletions(-) (limited to 'src/gpu') diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 3a2bbe864c..c26327eecf 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1440,6 +1440,14 @@ void GrContext::resolveRenderTarget(GrRenderTarget* target) { fGpu->resolveRenderTarget(target); } +void GrContext::discardRenderTarget(GrRenderTarget* target) { + SkASSERT(target); + ASSERT_OWNED_RESOURCE(target); + AutoRestoreEffects are; + AutoCheckFlush acf(this); + this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->discard(target); +} + void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft) { if (NULL == src || NULL == dst) { return; diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 8d3ded2d65..10698442b2 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -1019,6 +1019,7 @@ void GrDrawTargetCaps::reset() { fBufferLockSupport = false; fPathRenderingSupport = false; fDstReadInShaderSupport = false; + fDiscardRenderTargetSupport = false; fReuseScratchTextures = true; fGpuTracingSupport = false; @@ -1042,6 +1043,7 @@ GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { fBufferLockSupport = other.fBufferLockSupport; fPathRenderingSupport = other.fPathRenderingSupport; fDstReadInShaderSupport = other.fDstReadInShaderSupport; + fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport; fReuseScratchTextures = other.fReuseScratchTextures; fGpuTracingSupport = other.fGpuTracingSupport; @@ -1057,23 +1059,24 @@ GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { SkString GrDrawTargetCaps::dump() const { SkString r; static const char* gNY[] = {"NO", "YES"}; - r.appendf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]); - r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); - r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); - r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); - r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); - r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); - r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); - r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); - r.appendf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]); - r.appendf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]); - r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); - r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); - r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); - r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); - r.appendf("Max Texture Size : %d\n", fMaxTextureSize); - r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); - r.appendf("Max Sample Count : %d\n", fMaxSampleCount); + r.appendf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]); + r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); + r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); + r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); + r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); + r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); + r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); + r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); + r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); + r.appendf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]); + r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); + r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); + r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]); + r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); + r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); + r.appendf("Max Texture Size : %d\n", fMaxTextureSize); + r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); + r.appendf("Max Sample Count : %d\n", fMaxSampleCount); static const char* kConfigNames[] = { "Unknown", // kUnknown_GrPixelConfig diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 5b26ff5d56..6b3d4637cc 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -437,6 +437,12 @@ public: bool canIgnoreRect, GrRenderTarget* renderTarget = NULL) = 0; + /** + * Discards the contents render target. NULL indicates that the current render target should + * be discarded. + **/ + virtual void discard(GrRenderTarget* = NULL) = 0; + /** * Called at start and end of gpu trace marking * GR_CREATE_GPU_TRACE_MARKER(marker_str, target) will automatically call these at the start diff --git a/src/gpu/GrDrawTargetCaps.h b/src/gpu/GrDrawTargetCaps.h index b33217a125..a77bce4430 100644 --- a/src/gpu/GrDrawTargetCaps.h +++ b/src/gpu/GrDrawTargetCaps.h @@ -40,6 +40,7 @@ public: bool bufferLockSupport() const { return fBufferLockSupport; } bool pathRenderingSupport() const { return fPathRenderingSupport; } bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; } + bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; } bool gpuTracingSupport() const { return fGpuTracingSupport; } // Scratch textures not being reused means that those scratch textures @@ -71,6 +72,7 @@ protected: bool fBufferLockSupport : 1; bool fPathRenderingSupport : 1; bool fDstReadInShaderSupport : 1; + bool fDiscardRenderTargetSupport: 1; bool fReuseScratchTextures : 1; bool fGpuTracingSupport : 1; diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 178df7553a..8d34e6cf76 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -504,6 +504,7 @@ void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color, rect = &r; } Clear* clr = this->recordClear(); + GrColorIsPMAssert(color); clr->fColor = color; clr->fRect = *rect; clr->fCanIgnoreRect = canIgnoreRect; @@ -511,6 +512,20 @@ void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color, renderTarget->ref(); } +void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) { + if (!this->caps()->discardRenderTargetSupport()) { + return; + } + if (NULL == renderTarget) { + renderTarget = this->drawState()->getRenderTarget(); + SkASSERT(NULL != renderTarget); + } + Clear* clr = this->recordClear(); + clr->fColor = GrColor_ILLEGAL; + clr->fRenderTarget = renderTarget; + renderTarget->ref(); +} + void GrInOrderDrawBuffer::reset() { SkASSERT(1 == fGeoPoolStateStack.count()); this->resetVertexSource(); @@ -630,10 +645,14 @@ void GrInOrderDrawBuffer::flush() { ++currClip; break; case kClear_Cmd: - fDstGpu->clear(&fClears[currClear].fRect, - fClears[currClear].fColor, - fClears[currClear].fCanIgnoreRect, - fClears[currClear].fRenderTarget); + if (GrColor_ILLEGAL == fClears[currClear].fColor) { + fDstGpu->discard(fClears[currClear].fRenderTarget); + } else { + fDstGpu->clear(&fClears[currClear].fRect, + fClears[currClear].fColor, + fClears[currClear].fCanIgnoreRect, + fClears[currClear].fRenderTarget); + } ++currClear; break; case kCopySurface_Cmd: diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h index 72d0f9656e..0e0c57db3f 100644 --- a/src/gpu/GrInOrderDrawBuffer.h +++ b/src/gpu/GrInOrderDrawBuffer.h @@ -72,7 +72,9 @@ public: virtual void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect, - GrRenderTarget* renderTarget = NULL) SK_OVERRIDE; + GrRenderTarget* renderTarget) SK_OVERRIDE; + + virtual void discard(GrRenderTarget*) SK_OVERRIDE; virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE; @@ -125,6 +127,7 @@ private: GrDeviceCoordTexture fDstCopy; }; + // This is also used to record a discard by setting the color to GrColor_ILLEGAL struct Clear : public ::SkNoncopyable { Clear() : fRenderTarget(NULL) {} ~Clear() { SkSafeUnref(fRenderTarget); } diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp index f18df2cfa6..729aa0d469 100644 --- a/src/gpu/GrRenderTarget.cpp +++ b/src/gpu/GrRenderTarget.cpp @@ -54,6 +54,15 @@ void GrRenderTarget::resolve() { context->resolveRenderTarget(this); } +void GrRenderTarget::discard() { + // go through context so that all necessary flushing occurs + GrContext* context = this->getContext(); + if (NULL == context) { + return; + } + context->discardRenderTarget(this); +} + size_t GrRenderTarget::sizeInBytes() const { size_t colorBits; if (kUnknown_GrPixelConfig == fDesc.fConfig) { diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 47f3f0f0c8..bf7939ccee 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -45,7 +45,6 @@ void GrGLCaps::reset() { fUseNonVBOVertexAndIndexDynamicData = false; fIsCoreProfile = false; fFixedFunctionSupport = false; - fDiscardFBSupport = false; fFullClearIsFree = false; fDropsTileOnZeroDivide = false; } @@ -83,7 +82,6 @@ GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) { fUseNonVBOVertexAndIndexDynamicData = caps.fUseNonVBOVertexAndIndexDynamicData; fIsCoreProfile = caps.fIsCoreProfile; fFixedFunctionSupport = caps.fFixedFunctionSupport; - fDiscardFBSupport = caps.fDiscardFBSupport; fFullClearIsFree = caps.fFullClearIsFree; fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide; @@ -224,7 +222,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { fUseNonVBOVertexAndIndexDynamicData = true; } - fDiscardFBSupport = ctxInfo.hasExtension("GL_EXT_discard_framebuffer"); + fDiscardRenderTargetSupport = ctxInfo.hasExtension("GL_EXT_discard_framebuffer"); if (kARM_GrGLVendor == ctxInfo.vendor() || kImagination_GrGLVendor == ctxInfo.vendor()) { fFullClearIsFree = true; @@ -664,7 +662,6 @@ SkString GrGLCaps::dump() const { r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO")); r.appendf("Use non-VBO for dynamic data: %s\n", (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO")); - r.appendf("Discard FrameBuffer support: %s\n", (fDiscardFBSupport ? "YES" : "NO")); r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO")); r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO")); return r; diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 0939f80c26..21176d16dd 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -245,9 +245,6 @@ public: bool fixedFunctionSupport() const { return fFixedFunctionSupport; } - /// Is there support for discarding the frame buffer - bool discardFBSupport() const { return fDiscardFBSupport; } - bool fullClearIsFree() const { return fFullClearIsFree; } bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; } @@ -332,7 +329,6 @@ private: bool fUseNonVBOVertexAndIndexDynamicData : 1; bool fIsCoreProfile : 1; bool fFixedFunctionSupport : 1; - bool fDiscardFBSupport : 1; bool fFullClearIsFree : 1; bool fDropsTileOnZeroDivide : 1; diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h index 0dbd425f0d..a4dc2f782b 100644 --- a/src/gpu/gl/GrGLDefines.h +++ b/src/gpu/gl/GrGLDefines.h @@ -691,6 +691,11 @@ #define GR_GL_DEPTH_ATTACHMENT 0x8D00 #define GR_GL_STENCIL_ATTACHMENT 0x8D20 +// GL_EXT_discard_framebuffer +#define GR_GL_COLOR 0x1800 +#define GR_GL_DEPTH 0x1801 +#define GR_GL_STENCIL 0x1802 + #define GR_GL_NONE 0 #define GR_GL_FRAMEBUFFER_COMPLETE 0x8CD5 diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index dc2ef7d84e..78bf8f91cf 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -1295,6 +1295,25 @@ void GrGpuGL::onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) { GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT)); } +void GrGpuGL::discard(GrRenderTarget* renderTarget) { + if (NULL == renderTarget) { + renderTarget = this->drawState()->getRenderTarget(); + if (NULL == renderTarget) { + return; + } + } + + GrGLRenderTarget* glRT = static_cast(renderTarget); + if (renderTarget != fHWBoundRenderTarget) { + fHWBoundRenderTarget = NULL; + GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, glRT->renderFBOID())); + } + GrGLenum attachments[] = { GR_GL_COLOR }; + GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments), attachments)); + renderTarget->flagAsResolved(); +} + + void GrGpuGL::clearStencil() { if (NULL == this->getDrawState().getRenderTarget()) { return; diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 6a895750c5..e173aeff71 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -40,6 +40,8 @@ public: GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); } const GrGLCaps& glCaps() const { return *fGLContext.caps(); } + virtual void discard(GrRenderTarget*) SK_OVERRIDE; + // Used by GrGLProgram and GrGLTexGenProgramEffects to configure OpenGL state. void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture); void setProjectionMatrix(const SkMatrix& matrix, -- cgit v1.2.3