 Chromium Code Reviews
 Chromium Code Reviews Issue 22686002:
  Implement path cover with nv_path_rendering  (Closed) 
  Base URL: https://skia.googlecode.com/svn/trunk
    
  
    Issue 22686002:
  Implement path cover with nv_path_rendering  (Closed) 
  Base URL: https://skia.googlecode.com/svn/trunk| OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. | 
| 3 * | 3 * | 
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be | 
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. | 
| 6 */ | 6 */ | 
| 7 | 7 | 
| 8 | 8 | 
| 9 #include "GrGpuGL.h" | 9 #include "GrGpuGL.h" | 
| 10 #include "GrGLStencilBuffer.h" | 10 #include "GrGLStencilBuffer.h" | 
| (...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1673 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); | 1673 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); | 
| 1674 } | 1674 } | 
| 1675 const GrStencilSettings& even_odd_nv_path_stencil_settings() { | 1675 const GrStencilSettings& even_odd_nv_path_stencil_settings() { | 
| 1676 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, | 1676 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, | 
| 1677 kInvert_StencilOp, | 1677 kInvert_StencilOp, | 
| 1678 kInvert_StencilOp, | 1678 kInvert_StencilOp, | 
| 1679 kAlwaysIfInClip_StencilFunc, | 1679 kAlwaysIfInClip_StencilFunc, | 
| 1680 kOnes16, kOnes16, kOnes16); | 1680 kOnes16, kOnes16, kOnes16); | 
| 1681 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); | 1681 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); | 
| 1682 } | 1682 } | 
| 1683 | |
| 1684 GrGLenum sk_path_fill_type_to_gl_fill_mode(SkPath::FillType fill) { | |
| 1685 switch (fill) { | |
| 1686 default: | |
| 1687 GrCrash("Unexpected path fill."); | |
| 1688 /* fallthrough */; | |
| 1689 case SkPath::kWinding_FillType: | |
| 1690 return GR_GL_COUNT_UP; | |
| 1691 case SkPath::kEvenOdd_FillType: | |
| 1692 return GR_GL_INVERT; | |
| 1693 } | |
| 1694 } | |
| 1683 } | 1695 } | 
| 1684 | 1696 | 
| 1685 void GrGpuGL::setStencilPathSettings(const GrPath&, | 1697 const GrStencilSettings& GrGpuGL::getStencilPathSettings(const GrPath&, SkPath:: FillType fill) { | 
| 1686 SkPath::FillType fill, | |
| 1687 GrStencilSettings* settings) { | |
| 1688 switch (fill) { | 1698 switch (fill) { | 
| 1689 case SkPath::kEvenOdd_FillType: | |
| 1690 *settings = even_odd_nv_path_stencil_settings(); | |
| 1691 return; | |
| 1692 case SkPath::kWinding_FillType: | |
| 1693 *settings = winding_nv_path_stencil_settings(); | |
| 1694 return; | |
| 1695 default: | 1699 default: | 
| 1696 GrCrash("Unexpected path fill."); | 1700 GrCrash("Unexpected path fill."); | 
| 1701 /* fallthrough */; | |
| 1702 case SkPath::kWinding_FillType: | |
| 1703 return winding_nv_path_stencil_settings(); | |
| 1704 case SkPath::kEvenOdd_FillType: | |
| 1705 return even_odd_nv_path_stencil_settings(); | |
| 1697 } | 1706 } | 
| 1698 } | 1707 } | 
| 1699 | 1708 | 
| 1700 void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) { | 1709 void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) { | 
| 1701 SkASSERT(this->caps()->pathStencilingSupport()); | 1710 SkASSERT(this->caps()->pathStencilingSupport()); | 
| 1702 | 1711 | 
| 1703 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); | 1712 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); | 
| 1704 GrDrawState* drawState = this->drawState(); | 1713 GrDrawState* drawState = this->drawState(); | 
| 1705 SkASSERT(NULL != drawState->getRenderTarget()); | 1714 SkASSERT(NULL != drawState->getRenderTarget()); | 
| 1706 if (NULL == drawState->getRenderTarget()->getStencilBuffer()) { | 1715 if (NULL == drawState->getRenderTarget()->getStencilBuffer()) { | 
| 1707 return; | 1716 return; | 
| 1708 } | 1717 } | 
| 1709 | 1718 | 
| 1710 // Decide how to manipulate the stencil buffer based on the fill rule. | 1719 // Decide how to manipulate the stencil buffer based on the fill rule. | 
| 1711 // Also, assert that the stencil settings we set in setStencilPathSettings | |
| 1712 // are present. | |
| 1713 SkASSERT(!fStencilSettings.isTwoSided()); | 1720 SkASSERT(!fStencilSettings.isTwoSided()); | 
| 1714 GrGLenum fillMode; | 1721 GrGLenum fillMode = sk_path_fill_type_to_gl_fill_mode(fill); | 
| 1715 switch (fill) { | 1722 GrGLint writeMask = fStencilPathSettings.writeMask(GrStencilSettings::kFront _Face); | 
| 1716 case SkPath::kWinding_FillType: | |
| 1717 fillMode = GR_GL_COUNT_UP; | |
| 1718 SkASSERT(kIncClamp_StencilOp == | |
| 1719 fStencilSettings.passOp(GrStencilSettings::kFront_Face)); | |
| 1720 SkASSERT(kIncClamp_StencilOp == | |
| 1721 fStencilSettings.failOp(GrStencilSettings::kFront_Face)); | |
| 1722 break; | |
| 1723 case SkPath::kEvenOdd_FillType: | |
| 1724 fillMode = GR_GL_INVERT; | |
| 1725 SkASSERT(kInvert_StencilOp == | |
| 1726 fStencilSettings.passOp(GrStencilSettings::kFront_Face)); | |
| 1727 SkASSERT(kInvert_StencilOp == | |
| 1728 fStencilSettings.failOp(GrStencilSettings::kFront_Face)); | |
| 1729 break; | |
| 1730 default: | |
| 1731 // Only the above two fill rules are allowed. | |
| 1732 GrCrash("Unexpected path fill."); | |
| 1733 return; // suppress unused var warning. | |
| 1734 } | |
| 1735 GrGLint writeMask = fStencilSettings.writeMask(GrStencilSettings::kFront_Fac e); | |
| 1736 GL_CALL(StencilFillPath(id, fillMode, writeMask)); | 1723 GL_CALL(StencilFillPath(id, fillMode, writeMask)); | 
| 1737 } | 1724 } | 
| 1738 | 1725 | 
| 1726 void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) { | |
| 1727 SkASSERT(this->caps()->pathStencilingSupport()); | |
| 1728 | |
| 1729 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); | |
| 1730 GrDrawState* drawState = this->drawState(); | |
| 1731 SkASSERT(NULL != drawState->getRenderTarget()); | |
| 1732 if (NULL == drawState->getRenderTarget()->getStencilBuffer()) { | |
| 
Mark Kilgard
2013/09/13 15:42:24
Do we really expect to get here without a stencil
 
bsalomon
2013/09/13 20:25:28
It's not illegal for a caller to give us an FBO wi
 
Kimmo Kinnunen
2013/09/18 07:52:38
Done.
 | |
| 1733 return; | |
| 1734 } | |
| 1735 | |
| 1736 SkASSERT(!fStencilSettings.isTwoSided()); | |
| 1737 GrGLenum fillMode = sk_path_fill_type_to_gl_fill_mode(fill); | |
| 1738 GrGLint writeMask = fStencilPathSettings.writeMask(GrStencilSettings::kFront _Face); | |
| 1739 GL_CALL(StencilFillPath(id, fillMode, writeMask)); | |
| 1740 if (!fCurrentProgram->hasVertexShader()) { | |
| 1741 GL_CALL(CoverFillPath(id, GR_GL_CONVEX_HULL)); | |
| 
Chris Dalton
2013/09/13 19:49:58
I'd suggest using BOUNDING_BOX here.
Mark, though
 
Kimmo Kinnunen
2013/09/18 07:52:38
Done.
 | |
| 1742 } else { | |
| 
Mark Kilgard
2013/09/13 15:42:24
Is there a reason we would ever want to get into t
 
Chris Dalton
2013/09/13 19:49:58
Yes, the contract is that every time we draw a pat
 
bsalomon
2013/09/13 20:25:28
agreed
 
Kimmo Kinnunen
2013/09/18 07:52:38
I'm not sure I follow. I thought an effect can for
 
bsalomon
2013/09/18 14:24:22
Effects that require vertex shaders are only insta
 | |
| 1743 GrDrawState::AutoViewMatrixRestore avmr; | |
| 1744 SkMatrix vmi; | |
| 1745 SkRect bounds = SkRect::MakeLTRB(0, 0, | |
| 1746 SkIntToScalar(drawState->getRenderTarge t()->width()), | |
| 1747 SkIntToScalar(drawState->getRenderTarge t()->height())); | |
| 1748 | |
| 1749 // mapRect through persp matrix may not be correct | |
| 1750 if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewIn verse(&vmi)) { | |
| 1751 vmi.mapRect(&bounds); | |
| 1752 // theoretically could set bloat = 0, instead leave it because of ma trix inversion | |
| 1753 // precision. | |
| 1754 SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_Sca larHalf; | |
| 1755 bounds.outset(bloat, bloat); | |
| 1756 } else { | |
| 1757 avmr.setIdentity(drawState); | |
| 1758 } | |
| 1759 | |
| 1760 this->drawSimpleRect(bounds, NULL); | |
| 1761 } | |
| 1762 } | |
| 1763 | |
| 1739 void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { | 1764 void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { | 
| 1740 GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target); | 1765 GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target); | 
| 1741 if (rt->needsResolve()) { | 1766 if (rt->needsResolve()) { | 
| 1742 // Some extensions automatically resolves the texture when it is read. | 1767 // Some extensions automatically resolves the texture when it is read. | 
| 1743 if (this->glCaps().usesMSAARenderBuffers()) { | 1768 if (this->glCaps().usesMSAARenderBuffers()) { | 
| 1744 SkASSERT(rt->textureFBOID() != rt->renderFBOID()); | 1769 SkASSERT(rt->textureFBOID() != rt->renderFBOID()); | 
| 1745 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID())); | 1770 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID())); | 
| 1746 GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID())) ; | 1771 GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID())) ; | 
| 1747 // make sure we go through flushRenderTarget() since we've modified | 1772 // make sure we go through flushRenderTarget() since we've modified | 
| 1748 // the bound DRAW FBO ID. | 1773 // the bound DRAW FBO ID. | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1850 GR_GL_CALL(gl, StencilOp(glFailOp, glPassOp, glPassOp)); | 1875 GR_GL_CALL(gl, StencilOp(glFailOp, glPassOp, glPassOp)); | 
| 1851 } else { | 1876 } else { | 
| 1852 GR_GL_CALL(gl, StencilFuncSeparate(glFace, glFunc, ref, mask)); | 1877 GR_GL_CALL(gl, StencilFuncSeparate(glFace, glFunc, ref, mask)); | 
| 1853 GR_GL_CALL(gl, StencilMaskSeparate(glFace, writeMask)); | 1878 GR_GL_CALL(gl, StencilMaskSeparate(glFace, writeMask)); | 
| 1854 GR_GL_CALL(gl, StencilOpSeparate(glFace, glFailOp, glPassOp, glPassOp)); | 1879 GR_GL_CALL(gl, StencilOpSeparate(glFace, glFailOp, glPassOp, glPassOp)); | 
| 1855 } | 1880 } | 
| 1856 } | 1881 } | 
| 1857 } | 1882 } | 
| 1858 | 1883 | 
| 1859 void GrGpuGL::flushStencil(DrawType type) { | 1884 void GrGpuGL::flushStencil(DrawType type) { | 
| 1860 if (kStencilPath_DrawType == type) { | 1885 if ((kStencilPath_DrawType == type || kDrawPath_DrawType == type) && | 
| 1861 SkASSERT(!fStencilSettings.isTwoSided()); | 1886 fHWStencilPathSettings != fStencilPathSettings) { | 
| 1887 SkASSERT(!fStencilPathSettings.isTwoSided()); | |
| 1862 // Just the func, ref, and mask is set here. The op and write mask are p arams to the call | 1888 // Just the func, ref, and mask is set here. The op and write mask are p arams to the call | 
| 1863 // that draws the path to the SB (glStencilFillPath) | 1889 // that draws the path to the SB (glStencilFillPath) | 
| 1864 GrGLenum func = | 1890 GrGLenum func = | 
| 1865 gr_to_gl_stencil_func(fStencilSettings.func(GrStencilSettings::kFron t_Face)); | 1891 gr_to_gl_stencil_func(fStencilPathSettings.func(GrStencilSettings::k Front_Face)); | 
| 1866 GL_CALL(PathStencilFunc(func, | 1892 GL_CALL(PathStencilFunc(func, | 
| 1867 fStencilSettings.funcRef(GrStencilSettings::kFro nt_Face), | 1893 fStencilPathSettings.funcRef(GrStencilSettings:: kFront_Face), | 
| 1868 fStencilSettings.funcMask(GrStencilSettings::kFr ont_Face))); | 1894 fStencilPathSettings.funcMask(GrStencilSettings: :kFront_Face))); | 
| 1869 } else if (fHWStencilSettings != fStencilSettings) { | 1895 fHWStencilPathSettings = fStencilPathSettings; | 
| 1896 } | |
| 1897 | |
| 1898 if (kStencilPath_DrawType != type && fHWStencilSettings != fStencilSettings) { | |
| 1870 if (fStencilSettings.isDisabled()) { | 1899 if (fStencilSettings.isDisabled()) { | 
| 1871 if (kNo_TriState != fHWStencilTestEnabled) { | 1900 if (kNo_TriState != fHWStencilTestEnabled) { | 
| 1872 GL_CALL(Disable(GR_GL_STENCIL_TEST)); | 1901 GL_CALL(Disable(GR_GL_STENCIL_TEST)); | 
| 1873 fHWStencilTestEnabled = kNo_TriState; | 1902 fHWStencilTestEnabled = kNo_TriState; | 
| 1874 } | 1903 } | 
| 1875 } else { | 1904 } else { | 
| 1876 if (kYes_TriState != fHWStencilTestEnabled) { | 1905 if (kYes_TriState != fHWStencilTestEnabled) { | 
| 1877 GL_CALL(Enable(GR_GL_STENCIL_TEST)); | 1906 GL_CALL(Enable(GR_GL_STENCIL_TEST)); | 
| 1878 fHWStencilTestEnabled = kYes_TriState; | 1907 fHWStencilTestEnabled = kYes_TriState; | 
| 1879 } | 1908 } | 
| (...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2707 this->setVertexArrayID(gpu, 0); | 2736 this->setVertexArrayID(gpu, 0); | 
| 2708 } | 2737 } | 
| 2709 int attrCount = gpu->glCaps().maxVertexAttributes(); | 2738 int attrCount = gpu->glCaps().maxVertexAttributes(); | 
| 2710 if (fDefaultVertexArrayAttribState.count() != attrCount) { | 2739 if (fDefaultVertexArrayAttribState.count() != attrCount) { | 
| 2711 fDefaultVertexArrayAttribState.resize(attrCount); | 2740 fDefaultVertexArrayAttribState.resize(attrCount); | 
| 2712 } | 2741 } | 
| 2713 attribState = &fDefaultVertexArrayAttribState; | 2742 attribState = &fDefaultVertexArrayAttribState; | 
| 2714 } | 2743 } | 
| 2715 return attribState; | 2744 return attribState; | 
| 2716 } | 2745 } | 
| OLD | NEW |