aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-21 19:58:20 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-21 19:58:20 +0000
commita320194e4242ef0e5e758aea896bfd52bcb3dac7 (patch)
treef2025d8395a55204d523463c923f820c7a1ced02 /src/gpu/gl
parent8f7e1dac5c92bf1f53feb603a9bd249d53afa81a (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.cpp235
-rw-r--r--src/gpu/gl/GrGpuGL.h33
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp1
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;