Index: src/gpu/gl/GrGpuGL.cpp |
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp |
index 4f4bb0f93f51c40af99e37a361f822e2267892cf..b4111950c1ab6276a744c7df69cfa3967efa534d 100644 |
--- a/src/gpu/gl/GrGpuGL.cpp |
+++ b/src/gpu/gl/GrGpuGL.cpp |
@@ -356,6 +356,10 @@ void GrGpuGL::onResetContext(uint32_t resetBits) { |
fHWStencilTestEnabled = kUnknown_TriState; |
} |
+ if (resetBits & kPathRendering_GrGLBackendState && this->glCaps().pathRenderingSupport()) { |
+ fHWPathStencilSettings.invalidate(); |
+ } |
+ |
// Vertex |
if (resetBits & kVertex_GrGLBackendState) { |
fHWGeometryState.invalidate(); |
@@ -1270,7 +1274,7 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { |
} |
GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) { |
- SkASSERT(this->caps()->pathStencilingSupport()); |
+ SkASSERT(this->caps()->pathRenderingSupport()); |
return SkNEW_ARGS(GrGLPath, (this, inPath)); |
} |
@@ -1680,62 +1684,93 @@ const GrStencilSettings& even_odd_nv_path_stencil_settings() { |
kOnes16, kOnes16, kOnes16); |
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); |
} |
+GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) { |
+ switch (op) { |
+ default: |
+ GrCrash("Unexpected path fill."); |
+ /* fallthrough */; |
+ case kIncClamp_StencilOp: |
+ return GR_GL_COUNT_UP; |
+ case kInvert_StencilOp: |
+ return GR_GL_INVERT; |
+ } |
+} |
} |
-void GrGpuGL::setStencilPathSettings(const GrPath&, |
- SkPath::FillType fill, |
- GrStencilSettings* settings) { |
+const GrStencilSettings& GrGpuGL::getPathStencilSettingsForFillType(SkPath::FillType fill) { |
switch (fill) { |
- case SkPath::kEvenOdd_FillType: |
- *settings = even_odd_nv_path_stencil_settings(); |
- return; |
- case SkPath::kWinding_FillType: |
- *settings = winding_nv_path_stencil_settings(); |
- return; |
default: |
GrCrash("Unexpected path fill."); |
+ /* fallthrough */; |
+ case SkPath::kWinding_FillType: |
+ case SkPath::kInverseWinding_FillType: |
+ return winding_nv_path_stencil_settings(); |
+ case SkPath::kEvenOdd_FillType: |
+ case SkPath::kInverseEvenOdd_FillType: |
+ return even_odd_nv_path_stencil_settings(); |
} |
} |
void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) { |
- SkASSERT(this->caps()->pathStencilingSupport()); |
+ SkASSERT(this->caps()->pathRenderingSupport()); |
GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); |
GrDrawState* drawState = this->drawState(); |
SkASSERT(NULL != drawState->getRenderTarget()); |
- if (NULL == drawState->getRenderTarget()->getStencilBuffer()) { |
- return; |
- } |
+ SkASSERT(NULL != drawState->getRenderTarget()->getStencilBuffer()); |
// Decide how to manipulate the stencil buffer based on the fill rule. |
- // Also, assert that the stencil settings we set in setStencilPathSettings |
- // are present. |
- SkASSERT(!fStencilSettings.isTwoSided()); |
- GrGLenum fillMode; |
- switch (fill) { |
- case SkPath::kWinding_FillType: |
- fillMode = GR_GL_COUNT_UP; |
- SkASSERT(kIncClamp_StencilOp == |
- fStencilSettings.passOp(GrStencilSettings::kFront_Face)); |
- SkASSERT(kIncClamp_StencilOp == |
- fStencilSettings.failOp(GrStencilSettings::kFront_Face)); |
- break; |
- case SkPath::kEvenOdd_FillType: |
- fillMode = GR_GL_INVERT; |
- SkASSERT(kInvert_StencilOp == |
- fStencilSettings.passOp(GrStencilSettings::kFront_Face)); |
- SkASSERT(kInvert_StencilOp == |
- fStencilSettings.failOp(GrStencilSettings::kFront_Face)); |
- break; |
- default: |
- // Only the above two fill rules are allowed. |
- GrCrash("Unexpected path fill."); |
- return; // suppress unused var warning. |
- } |
- GrGLint writeMask = fStencilSettings.writeMask(GrStencilSettings::kFront_Face); |
+ SkASSERT(!fPathStencilSettings.isTwoSided()); |
+ |
+ GrGLenum fillMode = |
+ gr_stencil_op_to_gl_path_rendering_fill_mode(fPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); |
+ GrGLint writeMask = fPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); |
GL_CALL(StencilFillPath(id, fillMode, writeMask)); |
} |
+void GrGpuGL::onGpuFillPath(const GrPath* path, SkPath::FillType fill) { |
+ SkASSERT(this->caps()->pathRenderingSupport()); |
+ |
+ GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); |
+ GrDrawState* drawState = this->drawState(); |
+ SkASSERT(NULL != drawState->getRenderTarget()); |
+ SkASSERT(NULL != drawState->getRenderTarget()->getStencilBuffer()); |
+ |
+ SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill); |
+ SkASSERT(!fPathStencilSettings.isTwoSided()); |
+ GrGLenum fillMode = |
+ gr_stencil_op_to_gl_path_rendering_fill_mode(fPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); |
+ GrGLint writeMask = fPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); |
+ GL_CALL(StencilFillPath(id, fillMode, writeMask)); |
+ |
+ if (!fCurrentProgram->hasVertexShader() && nonInvertedFill == fill) { |
+ GL_CALL(CoverFillPath(id, GR_GL_BOUNDING_BOX)); |
+ } else { |
+ GrDrawState::AutoViewMatrixRestore avmr; |
+ SkRect bounds; |
+ if (nonInvertedFill == fill) { |
+ bounds = path->getBounds(); |
+ } else { |
+ bounds = SkRect::MakeLTRB(0, 0, |
+ SkIntToScalar(drawState->getRenderTarget()->width()), |
+ SkIntToScalar(drawState->getRenderTarget()->height())); |
+ SkMatrix vmi; |
+ // mapRect through persp matrix may not be correct |
+ if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) { |
+ vmi.mapRect(&bounds); |
+ // theoretically could set bloat = 0, instead leave it because of matrix inversion |
+ // precision. |
+ SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_ScalarHalf; |
+ bounds.outset(bloat, bloat); |
+ } else { |
+ avmr.setIdentity(drawState); |
+ } |
+ } |
+ |
+ this->drawSimpleRect(bounds, NULL); |
+ } |
+} |
+ |
void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { |
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target); |
if (rt->needsResolve()) { |
@@ -1857,16 +1892,21 @@ void set_gl_stencil(const GrGLInterface* gl, |
} |
void GrGpuGL::flushStencil(DrawType type) { |
- if (kStencilPath_DrawType == type) { |
- SkASSERT(!fStencilSettings.isTwoSided()); |
+ if ((kStencilPath_DrawType == type || kFillPath_DrawType == type) && |
+ fHWPathStencilSettings != fPathStencilSettings) { |
+ |
// Just the func, ref, and mask is set here. The op and write mask are params to the call |
// that draws the path to the SB (glStencilFillPath) |
GrGLenum func = |
- gr_to_gl_stencil_func(fStencilSettings.func(GrStencilSettings::kFront_Face)); |
+ gr_to_gl_stencil_func(fPathStencilSettings.func(GrStencilSettings::kFront_Face)); |
GL_CALL(PathStencilFunc(func, |
- fStencilSettings.funcRef(GrStencilSettings::kFront_Face), |
- fStencilSettings.funcMask(GrStencilSettings::kFront_Face))); |
- } else if (fHWStencilSettings != fStencilSettings) { |
+ fPathStencilSettings.funcRef(GrStencilSettings::kFront_Face), |
+ fPathStencilSettings.funcMask(GrStencilSettings::kFront_Face))); |
+ |
+ fHWPathStencilSettings = fPathStencilSettings; |
+ } |
+ |
+ if (kStencilPath_DrawType != type && fHWStencilSettings != fStencilSettings) { |
if (fStencilSettings.isDisabled()) { |
if (kNo_TriState != fHWStencilTestEnabled) { |
GL_CALL(Disable(GR_GL_STENCIL_TEST)); |