diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-06-21 19:58:20 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-06-21 19:58:20 +0000 |
commit | a320194e4242ef0e5e758aea896bfd52bcb3dac7 (patch) | |
tree | f2025d8395a55204d523463c923f820c7a1ced02 /src/gpu/gl | |
parent | 8f7e1dac5c92bf1f53feb603a9bd249d53afa81a (diff) |
Make GrClipMaskManager configure the stencil and scissor on GrGpu
Review URL: http://codereview.appspot.com/6308096/
git-svn-id: http://skia.googlecode.com/svn/trunk@4288 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 235 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 33 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 1 |
3 files changed, 105 insertions, 164 deletions
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 5c1764cf29..76a7a63361 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -9,6 +9,7 @@ #include "GrGpuGL.h" #include "GrGLStencilBuffer.h" #include "GrGLPath.h" +#include "GrTemplates.h" #include "GrTypes.h" #include "SkTemplates.h" @@ -496,21 +497,16 @@ void GrGpuGL::onResetContext() { fHWBoundTextures[s] = NULL; } - fHWBounds.fScissorRect.invalidate(); - // set to true to force disableScissor to make a GL call. - fHWBounds.fScissorEnabled = true; - this->disableScissor(); + fHWScissorSettings.invalidate(); - fHWBounds.fViewportRect.invalidate(); + fHWViewport.invalidate(); fHWStencilSettings.invalidate(); - // This is arbitrary. The above invalidate ensures a full setup of the - // stencil on the next draw. - fHWStencilClipMode = GrClipMaskManager::kRespectClip_StencilClipMode; + fHWStencilTestEnabled = kUnknown_TriState; fHWGeometryState.fIndexBuffer = NULL; fHWGeometryState.fVertexBuffer = NULL; - + fHWGeometryState.fArrayPtrsDirty = true; fHWBoundRenderTarget = NULL; @@ -1333,7 +1329,7 @@ GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) { return path; } -void GrGpuGL::enableScissoring(const GrIRect& rect) { +void GrGpuGL::flushScissor() { const GrDrawState& drawState = this->getDrawState(); const GrGLRenderTarget* rt = static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget()); @@ -1341,28 +1337,31 @@ void GrGpuGL::enableScissoring(const GrIRect& rect) { GrAssert(NULL != rt); const GrGLIRect& vp = rt->getViewport(); - GrGLIRect scissor; - scissor.setRelativeTo(vp, rect.fLeft, rect.fTop, - rect.width(), rect.height()); - if (scissor.contains(vp)) { - disableScissor(); - return; - } - - if (fHWBounds.fScissorRect != scissor) { - scissor.pushToGLScissor(this->glInterface()); - fHWBounds.fScissorRect = scissor; - } - if (!fHWBounds.fScissorEnabled) { - GL_CALL(Enable(GR_GL_SCISSOR_TEST)); - fHWBounds.fScissorEnabled = true; + if (fScissorState.fEnabled) { + GrGLIRect scissor; + scissor.setRelativeTo(vp, + fScissorState.fRect.fLeft, + fScissorState.fRect.fTop, + fScissorState.fRect.width(), + fScissorState.fRect.height()); + // if the scissor fully contains the viewport then we fall through and + // disable the scissor test. + if (!scissor.contains(vp)) { + if (fHWScissorSettings.fRect != scissor) { + scissor.pushToGLScissor(this->glInterface()); + fHWScissorSettings.fRect = scissor; + } + if (kYes_TriState != fHWScissorSettings.fEnabled) { + GL_CALL(Enable(GR_GL_SCISSOR_TEST)); + fHWScissorSettings.fEnabled = kYes_TriState; + } + return; + } } -} - -void GrGpuGL::disableScissor() { - if (fHWBounds.fScissorEnabled) { + if (kNo_TriState != fHWScissorSettings.fEnabled) { GL_CALL(Disable(GR_GL_SCISSOR_TEST)); - fHWBounds.fScissorEnabled = false; + fHWScissorSettings.fEnabled = kNo_TriState; + return; } } @@ -1384,10 +1383,12 @@ void GrGpuGL::onClear(const GrIRect* rect, GrColor color) { } } this->flushRenderTarget(rect); - if (NULL != rect) - this->enableScissoring(*rect); - else - this->disableScissor(); + GrAutoTRestore<ScissorState> asr(&fScissorState); + fScissorState.fEnabled = (NULL != rect); + if (fScissorState.fEnabled) { + fScissorState.fRect = *rect; + } + this->flushScissor(); GrGLfloat r, g, b, a; static const GrGLfloat scale255 = 1.f / 255.f; @@ -1413,7 +1414,9 @@ void GrGpuGL::clearStencil() { this->flushRenderTarget(&GrIRect::EmptyIRect()); - this->disableScissor(); + GrAutoTRestore<ScissorState> asr(&fScissorState); + fScissorState.fEnabled = false; + this->flushScissor(); GL_CALL(StencilMask(0xffffffff)); GL_CALL(ClearStencil(0)); @@ -1448,7 +1451,12 @@ void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) { value = 0; } this->flushRenderTarget(&GrIRect::EmptyIRect()); - this->enableScissoring(rect); + + GrAutoTRestore<ScissorState> asr(&fScissorState); + fScissorState.fEnabled = true; + fScissorState.fRect = rect; + this->flushScissor(); + GL_CALL(StencilMask((uint32_t) clipStencilMask)); GL_CALL(ClearStencil(value)); GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); @@ -1625,9 +1633,9 @@ void GrGpuGL::flushRenderTarget(const GrIRect* bound) { #endif fHWBoundRenderTarget = rt; const GrGLIRect& vp = rt->getViewport(); - if (fHWBounds.fViewportRect != vp) { + if (fHWViewport != vp) { vp.pushToGLViewport(this->glInterface()); - fHWBounds.fViewportRect = vp; + fHWViewport = vp; } } if (NULL == bound || !bound->isEmpty()) { @@ -1747,28 +1755,25 @@ void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { const GrGLIRect& vp = rt->getViewport(); const GrIRect dirtyRect = rt->getResolveRect(); GrGLIRect r; - r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop, + r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop, dirtyRect.width(), dirtyRect.height()); + GrAutoTRestore<ScissorState> asr; if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) { // Apple's extension uses the scissor as the blit bounds. -#if 1 - GL_CALL(Enable(GR_GL_SCISSOR_TEST)); - GL_CALL(Scissor(r.fLeft, r.fBottom, - r.fWidth, r.fHeight)); - GL_CALL(ResolveMultisampleFramebuffer()); - fHWBounds.fScissorRect.invalidate(); - fHWBounds.fScissorEnabled = true; -#else - this->enableScissoring(dirtyRect); + asr.reset(&fScissorState); + fScissorState.fEnabled = true; + fScissorState.fRect = dirtyRect; + this->flushScissor(); GL_CALL(ResolveMultisampleFramebuffer()); -#endif } else { if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) { // this respects the scissor during the blit, so disable it. GrAssert(GrGLCaps::kDesktopEXT_MSFBOType == this->glCaps().msFBOType()); - this->disableScissor(); + asr.reset(&fScissorState); + fScissorState.fEnabled = false; + this->flushScissor(); } int right = r.fLeft + r.fWidth; int top = r.fBottom + r.fHeight; @@ -1832,16 +1837,16 @@ GrGLenum gr_to_gl_stencil_op(GrStencilOp op) { } void set_gl_stencil(const GrGLInterface* gl, + const GrStencilSettings& settings, GrGLenum glFace, - GrStencilFunc func, - GrStencilOp failOp, - GrStencilOp passOp, - unsigned int ref, - unsigned int mask, - unsigned int writeMask) { - GrGLenum glFunc = gr_to_gl_stencil_func(func); - GrGLenum glFailOp = gr_to_gl_stencil_op(failOp); - GrGLenum glPassOp = gr_to_gl_stencil_op(passOp); + GrStencilSettings::Face grFace) { + GrGLenum glFunc = gr_to_gl_stencil_func(settings.func(grFace)); + GrGLenum glFailOp = gr_to_gl_stencil_op(settings.failOp(grFace)); + GrGLenum glPassOp = gr_to_gl_stencil_op(settings.passOp(grFace)); + + GrGLint ref = settings.funcRef(grFace); + GrGLint mask = settings.funcMask(grFace); + GrGLint writeMask = settings.writeMask(grFace); if (GR_GL_FRONT_AND_BACK == glFace) { // we call the combined func just in case separate stencil is not @@ -1858,112 +1863,36 @@ void set_gl_stencil(const GrGLInterface* gl, } void GrGpuGL::flushStencil() { - const GrDrawState& drawState = this->getDrawState(); - - // use stencil for clipping if clipping is enabled and the clip - // has been written into the stencil. - GrClipMaskManager::StencilClipMode clipMode; - if (fClipMaskManager.isClipInStencil() && - drawState.isClipState()) { - clipMode = GrClipMaskManager::kRespectClip_StencilClipMode; - // We can't be modifying the clip and respecting it at the same time. - GrAssert(!drawState.isStateFlagEnabled(kModifyStencilClip_StateBit)); - } else if (drawState.isStateFlagEnabled(kModifyStencilClip_StateBit)) { - clipMode = GrClipMaskManager::kModifyClip_StencilClipMode; - } else { - clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode; - } - - // The caller may not be using the stencil buffer but we may need to enable - // it in order to respect a stencil clip. - const GrStencilSettings* settings = &drawState.getStencil(); - if (settings->isDisabled() && - GrClipMaskManager::kRespectClip_StencilClipMode == clipMode) { - settings = GetClipStencilSettings(); - } - - // TODO: dynamically attach a stencil buffer - int stencilBits = 0; - GrStencilBuffer* stencilBuffer = - drawState.getRenderTarget()->getStencilBuffer(); - if (NULL != stencilBuffer) { - stencilBits = stencilBuffer->bits(); - } - GrAssert(stencilBits || settings->isDisabled()); - - bool updateStencilSettings = stencilBits > 0 && - ((fHWStencilSettings != *settings) || - (fHWStencilClipMode != clipMode)); - if (updateStencilSettings) { - if (settings->isDisabled()) { + if (fStencilSettings.isDisabled()) { + if (kNo_TriState != fHWStencilTestEnabled) { GL_CALL(Disable(GR_GL_STENCIL_TEST)); - } else { + fHWStencilTestEnabled = kNo_TriState; + } + } else { + if (kYes_TriState != fHWStencilTestEnabled) { GL_CALL(Enable(GR_GL_STENCIL_TEST)); - #if GR_DEBUG - if (!this->getCaps().fStencilWrapOpsSupport) { - GrAssert(settings->frontPassOp() != kIncWrap_StencilOp); - GrAssert(settings->frontPassOp() != kDecWrap_StencilOp); - GrAssert(settings->frontFailOp() != kIncWrap_StencilOp); - GrAssert(settings->backFailOp() != kDecWrap_StencilOp); - GrAssert(settings->backPassOp() != kIncWrap_StencilOp); - GrAssert(settings->backPassOp() != kDecWrap_StencilOp); - GrAssert(settings->backFailOp() != kIncWrap_StencilOp); - GrAssert(settings->frontFailOp() != kDecWrap_StencilOp); - } - #endif - - unsigned int frontRef = settings->frontFuncRef(); - unsigned int frontMask = settings->frontFuncMask(); - unsigned int frontWriteMask = settings->frontWriteMask(); - - GrStencilFunc frontFunc = - fClipMaskManager.adjustStencilParams(settings->frontFunc(), - clipMode, - stencilBits, - &frontRef, - &frontMask, - &frontWriteMask); + fHWStencilTestEnabled = kYes_TriState; + } + } + if (fHWStencilSettings != fStencilSettings) { + if (!fStencilSettings.isDisabled()) { if (this->getCaps().fTwoSidedStencilSupport) { - unsigned int backRef = settings->backFuncRef(); - unsigned int backMask = settings->backFuncMask(); - unsigned int backWriteMask = settings->backWriteMask(); - - GrStencilFunc backFunc = - fClipMaskManager.adjustStencilParams(settings->frontFunc(), - clipMode, - stencilBits, - &backRef, - &backMask, - &backWriteMask); set_gl_stencil(this->glInterface(), + fStencilSettings, GR_GL_FRONT, - frontFunc, - settings->frontFailOp(), - settings->frontPassOp(), - frontRef, - frontMask, - frontWriteMask); + GrStencilSettings::kFront_Face); set_gl_stencil(this->glInterface(), + fStencilSettings, GR_GL_BACK, - backFunc, - settings->backFailOp(), - settings->backPassOp(), - backRef, - backMask, - backWriteMask); + GrStencilSettings::kBack_Face); } else { set_gl_stencil(this->glInterface(), + fStencilSettings, GR_GL_FRONT_AND_BACK, - frontFunc, - settings->frontFailOp(), - settings->frontPassOp(), - frontRef, - frontMask, - frontWriteMask); + GrStencilSettings::kFront_Face); } } - fHWStencilSettings = *settings; - fHWStencilClipMode = clipMode; + fHWStencilSettings = fStencilSettings; } } diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 51e49ec1ec..6220efafe4 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -108,8 +108,6 @@ protected: uint32_t vertexCount, uint32_t numVertices) SK_OVERRIDE; virtual void onGpuStencilPath(const GrPath&, GrPathFill) SK_OVERRIDE; - virtual void enableScissoring(const GrIRect& rect) SK_OVERRIDE; - virtual void disableScissor() SK_OVERRIDE; virtual void clearStencil() SK_OVERRIDE; virtual void clearStencilClip(const GrIRect& rect, @@ -206,6 +204,10 @@ private: }; // binds the texture and sets its texture params + // This may also perform a downsample on the src texture which may or may + // not modify the scissor test and rect. So in flushGraphicsState a + // call to flushScissor must occur after all textures have been flushed via + // this function. void flushBoundTextureAndParams(int stage); // sets the texture matrix and domain for the currently bound program @@ -232,6 +234,10 @@ private: // flushes dithering, color-mask, and face culling stat void flushMiscFixedFunctionState(); + // flushes the scissor. see the note on flushBoundTextureAndParams about + // flushing the scissor after that function is called. + void flushScissor(); + static void DeleteProgram(const GrGLInterface* gl, CachedData* programData); @@ -304,19 +310,24 @@ private: GrColor fHWConstAttribColor; GrColor fHWConstAttribCoverage; - // last scissor / viewport scissor state seen by the GL. - struct { - bool fScissorEnabled; - GrGLIRect fScissorRect; - GrGLIRect fViewportRect; - } fHWBounds; - enum TriState { kNo_TriState, kYes_TriState, kUnknown_TriState }; + // last scissor / viewport scissor state seen by the GL. + struct { + TriState fEnabled; + GrGLIRect fRect; + void invalidate() { + fEnabled = kUnknown_TriState; + fRect.invalidate(); + } + } fHWScissorSettings; + + GrGLIRect fHWViewport; + struct { size_t fVertexOffset; GrVertexLayout fVertexLayout; @@ -349,8 +360,8 @@ private: } } fHWAAState; - GrClipMaskManager::StencilClipMode fHWStencilClipMode; - GrStencilSettings fHWStencilSettings; + GrStencilSettings fHWStencilSettings; + TriState fHWStencilTestEnabled; GrDrawState::DrawFace fHWDrawFace; TriState fHWWriteToColor; diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index f8d71ffbf4..3ad352070a 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -454,6 +454,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { } } this->flushColorMatrix(); + this->flushScissor(); GrIRect* rect = NULL; GrIRect clipBounds; |