diff options
Diffstat (limited to 'src/gpu/gl/GrGpuGL.cpp')
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 130 |
1 files changed, 107 insertions, 23 deletions
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 2662f8e0b5..48ccd5daf7 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -268,6 +268,8 @@ void GrGpuGL::initCaps() { fCaps.fMaxRenderTargetSize = GrMin(fCaps.fMaxTextureSize, fCaps.fMaxRenderTargetSize); fCaps.fFSAASupport = GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType(); + fCaps.fPathStencilingSupport = GR_GL_USE_NV_PATH_RENDERING && + this->hasExtension("GL_NV_path_rendering"); // Enable supported shader-related caps if (kDesktop_GrGLBinding == this->glBinding()) { @@ -511,6 +513,8 @@ void GrGpuGL::onResetContext() { fHWBoundRenderTarget = NULL; + fHWPathMatrixState.invalidate(); + // we assume these values if (this->glCaps().unpackRowLengthSupport()) { GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); @@ -1322,11 +1326,8 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { } GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) { - GrPath* path = NULL; - if (fCaps.fPathStencilingSupport) { - path = new GrGLPath(this, inPath); - } - return path; + GrAssert(fCaps.fPathStencilingSupport); + return new GrGLPath(this, inPath); } void GrGpuGL::flushScissor() { @@ -1735,8 +1736,78 @@ void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type, #endif } -void GrGpuGL::onGpuStencilPath(const GrPath&, GrPathFill) { - GrCrash("Not implemented yet. Should not get here."); +namespace { +const GrStencilSettings& winding_nv_path_stencil_settings() { + GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, + kIncClamp_StencilOp, + kIncClamp_StencilOp, + kAlwaysIfInClip_StencilFunc, + ~0, ~0, ~0); + return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); +} +const GrStencilSettings& even_odd_nv_path_stencil_settings() { + GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, + kInvert_StencilOp, + kInvert_StencilOp, + kAlwaysIfInClip_StencilFunc, + ~0, ~0, ~0); + return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); +} +} + + +void GrGpuGL::setStencilPathSettings(const GrPath&, + GrPathFill fill, + GrStencilSettings* settings) { + switch (fill) { + case kEvenOdd_GrPathFill: + *settings = even_odd_nv_path_stencil_settings(); + return; + case kWinding_GrPathFill: + *settings = winding_nv_path_stencil_settings(); + return; + default: + GrCrash("Unexpected path fill."); + } +} + +void GrGpuGL::onGpuStencilPath(const GrPath* path, GrPathFill fill) { + GrAssert(fCaps.fPathStencilingSupport); + + GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); + GrDrawState* drawState = this->drawState(); + GrAssert(NULL != drawState->getRenderTarget()); + if (NULL == drawState->getRenderTarget()->getStencilBuffer()) { + return; + } + + // Decide how to manipulate the stencil buffer based on the fill rule. + // Also, assert that the stencil settings we set in setStencilPathSettings + // are present. + GrAssert(!fStencilSettings.isTwoSided()); + GrGLenum fillMode; + switch (fill) { + case kWinding_GrPathFill: + fillMode = GR_GL_COUNT_UP; + GrAssert(kIncClamp_StencilOp == + fStencilSettings.passOp(GrStencilSettings::kFront_Face)); + GrAssert(kIncClamp_StencilOp == + fStencilSettings.failOp(GrStencilSettings::kFront_Face)); + break; + case kEvenOdd_GrPathFill: + fillMode = GR_GL_INVERT; + GrAssert(kInvert_StencilOp == + fStencilSettings.passOp(GrStencilSettings::kFront_Face)); + GrAssert(kInvert_StencilOp == + fStencilSettings.failOp(GrStencilSettings::kFront_Face)); + break; + default: + // Only the above two fill rules are allowed. + GrCrash("Unexpected path fill."); + } + GrGLint writeMask = fStencilSettings.writeMask(GrStencilSettings::kFront_Face); + GL_CALL(StencilFillPath(id, fillMode, writeMask)); + //GrPrintf("\tStencilFillPath ID: %d\n", id); } void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { @@ -1863,19 +1934,28 @@ void set_gl_stencil(const GrGLInterface* gl, } } -void GrGpuGL::flushStencil() { - if (fStencilSettings.isDisabled()) { - if (kNo_TriState != fHWStencilTestEnabled) { - GL_CALL(Disable(GR_GL_STENCIL_TEST)); - fHWStencilTestEnabled = kNo_TriState; - } - } else { - if (kYes_TriState != fHWStencilTestEnabled) { - GL_CALL(Enable(GR_GL_STENCIL_TEST)); - fHWStencilTestEnabled = kYes_TriState; +void GrGpuGL::flushStencil(DrawType type) { + if (kStencilPath_DrawType == type) { + GrAssert(!fStencilSettings.isTwoSided()); + // 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)); + GL_CALL(PathStencilFunc(func, + fStencilSettings.funcRef(GrStencilSettings::kFront_Face), + fStencilSettings.funcMask(GrStencilSettings::kFront_Face))); + } else if (fHWStencilSettings != fStencilSettings) { + if (fStencilSettings.isDisabled()) { + if (kNo_TriState != fHWStencilTestEnabled) { + GL_CALL(Disable(GR_GL_STENCIL_TEST)); + fHWStencilTestEnabled = kNo_TriState; + } + } else { + if (kYes_TriState != fHWStencilTestEnabled) { + GL_CALL(Enable(GR_GL_STENCIL_TEST)); + fHWStencilTestEnabled = kYes_TriState; + } } - } - if (fHWStencilSettings != fStencilSettings) { if (!fStencilSettings.isDisabled()) { if (this->getCaps().fTwoSidedStencilSupport) { set_gl_stencil(this->glInterface(), @@ -1897,7 +1977,7 @@ void GrGpuGL::flushStencil() { } } -void GrGpuGL::flushAAState(bool isLines) { +void GrGpuGL::flushAAState(DrawType type) { const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); if (kDesktop_GrGLBinding == this->glBinding()) { // ES doesn't support toggling GL_MULTISAMPLE and doesn't have @@ -1905,7 +1985,7 @@ void GrGpuGL::flushAAState(bool isLines) { // we prefer smooth lines over multisampled lines bool smoothLines = false; - if (isLines) { + if (kDrawLines_DrawType == type) { smoothLines = this->willUseHWAALines(); if (smoothLines) { if (kYes_TriState != fHWAAState.fSmoothLineEnabled) { @@ -1925,8 +2005,12 @@ void GrGpuGL::flushAAState(bool isLines) { } } } - if (!smoothLines && rt->isMultisampled()) { - if (this->getDrawState().isHWAntialiasState()) { + if (!smoothLines && rt->isMultisampled()) { + // FIXME: GL_NV_pr doesn't seem to like MSAA disabled. The paths + // convex hulls of each segment appear to get filled. + bool enableMSAA = kStencilPath_DrawType == type || + this->getDrawState().isHWAntialiasState(); + if (enableMSAA) { if (kYes_TriState != fHWAAState.fMSAAEnabled) { GL_CALL(Enable(GR_GL_MULTISAMPLE)); fHWAAState.fMSAAEnabled = kYes_TriState; |