diff options
author | 2014-07-29 15:25:51 -0700 | |
---|---|---|
committer | 2014-07-29 15:25:51 -0700 | |
commit | c8f520466701a14cf2fb86d3f2d3c70983cb4518 (patch) | |
tree | ba37430ec889b9664f5f2f4d59f1c618ff7e72d9 /src | |
parent | a14da251c29a8f9e6db37648e2c41c8bbf0af19b (diff) |
Incorporate glStencilThenCover* nvpr methods
Adds the glStencilThenCover* nvpr methods to GrGLInterface and starts
using them. When drawing multible paths, this will make it so we only
have to send the index/transform data once. It will also allow the
driver to save time internally.
The glStencilThenCover* methods are a newer addition, so they aren't
available on every driver. In the event that they are not present, we
emulate them using the existing glStencil*/glCover* methods.
BUG=skia:
R=markkilgard@gmail.com, bsalomon@google.com
Author: cdalton@nvidia.com
Review URL: https://codereview.chromium.org/423173004
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/gl/GrGLAssembleGLESInterface.h | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLAssembleInterface.cpp | 115 | ||||
-rw-r--r-- | src/gpu/gl/GrGLInterface.cpp | 6 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 59 |
4 files changed, 159 insertions, 25 deletions
diff --git a/src/gpu/gl/GrGLAssembleGLESInterface.h b/src/gpu/gl/GrGLAssembleGLESInterface.h index d3ebebd756..8162c2d9b5 100644 --- a/src/gpu/gl/GrGLAssembleGLESInterface.h +++ b/src/gpu/gl/GrGLAssembleGLESInterface.h @@ -276,6 +276,10 @@ static const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get GET_PROC_SUFFIX(CoverStrokePath, NV); GET_PROC_SUFFIX(CoverFillPathInstanced, NV); GET_PROC_SUFFIX(CoverStrokePathInstanced, NV); + GET_PROC_SUFFIX(StencilThenCoverFillPath, NV); + GET_PROC_SUFFIX(StencilThenCoverStrokePath, NV); + GET_PROC_SUFFIX(StencilThenCoverFillPathInstanced, NV); + GET_PROC_SUFFIX(StencilThenCoverStrokePathInstanced, NV); GET_PROC_SUFFIX(ProgramPathFragmentInputGen, NV); } diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp index c6b3f93793..4ae50ba391 100644 --- a/src/gpu/gl/GrGLAssembleInterface.cpp +++ b/src/gpu/gl/GrGLAssembleInterface.cpp @@ -14,6 +14,12 @@ #define GET_PROC_SUFFIX(F, S) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F #S) #define GET_PROC_LOCAL(F) GrGL ## F ## Proc F = (GrGL ## F ## Proc) get(ctx, "gl" #F) +// The glStencilThenCover* methods are a new addition to NV_path_rendering. They +// aren't available on all drivers. In the event that they are not present, this +// function can be used to add methods to the given GrGLInterface that emulate +// them using the existing glStencil*/glCover* methods. +static void emulate_nvpr_stencil_then_cover(GrGLInterface*); + const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) { GET_PROC_LOCAL(GetString); GET_PROC_LOCAL(GetStringi); @@ -239,7 +245,18 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) { GET_PROC_SUFFIX(CoverStrokePath, NV); GET_PROC_SUFFIX(CoverFillPathInstanced, NV); GET_PROC_SUFFIX(CoverStrokePathInstanced, NV); + GET_PROC_SUFFIX(StencilThenCoverFillPath, NV); + GET_PROC_SUFFIX(StencilThenCoverStrokePath, NV); + GET_PROC_SUFFIX(StencilThenCoverFillPathInstanced, NV); + GET_PROC_SUFFIX(StencilThenCoverStrokePathInstanced, NV); GET_PROC_SUFFIX(ProgramPathFragmentInputGen, NV); + + if (NULL == interface->fFunctions.fStencilThenCoverFillPath || + NULL == interface->fFunctions.fStencilThenCoverStrokePath || + NULL == interface->fFunctions.fStencilThenCoverFillPathInstanced || + NULL == interface->fFunctions.fStencilThenCoverFillPathInstanced) { + emulate_nvpr_stencil_then_cover(interface); + } } if (extensions.has("GL_EXT_debug_marker")) { @@ -266,3 +283,101 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) { return interface; } + +static GrGLStencilFillPathProc gStencilFillPath; +static GrGLCoverFillPathProc gCoverFillPath; +static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_fill_path( + GrGLuint path, GrGLenum fillMode, + GrGLuint mask, GrGLenum coverMode) { + gStencilFillPath(path, fillMode, mask); + gCoverFillPath(path, coverMode); +} + + +static GrGLStencilStrokePathProc gStencilStrokePath; +static GrGLCoverStrokePathProc gCoverStrokePath; +static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_stroke_path( + GrGLuint path, GrGLint reference, + GrGLuint mask, GrGLenum coverMode) { + gStencilStrokePath(path, reference, mask); + gCoverStrokePath(path, coverMode); +} + +static GrGLStencilFillPathInstancedProc gStencilFillPathInstanced; +static GrGLCoverFillPathInstancedProc gCoverFillPathInstanced; +static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_fill_path_instanced( + GrGLsizei numPaths, GrGLenum pathNameType, + const GrGLvoid *paths, GrGLuint pathBase, + GrGLenum fillMode, GrGLuint mask, + GrGLenum coverMode, GrGLenum transformType, + const GrGLfloat *transformValues) { + gStencilFillPathInstanced(numPaths, pathNameType, paths, pathBase, + fillMode, mask, transformType, transformValues); + gCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, + coverMode, transformType, transformValues); +} + +static GrGLStencilStrokePathInstancedProc gStencilStrokePathInstanced; +static GrGLCoverStrokePathInstancedProc gCoverStrokePathInstanced; +static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_stroke_path_instanced( + GrGLsizei numPaths, GrGLenum pathNameType, + const GrGLvoid *paths, GrGLuint pathBase, + GrGLint reference, GrGLuint mask, + GrGLenum coverMode, GrGLenum transformType, + const GrGLfloat *transformValues) { + gStencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, + reference, mask, transformType, transformValues); + gCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, + coverMode, transformType, transformValues); +} + +static void emulate_nvpr_stencil_then_cover(GrGLInterface* interface) { + if (NULL == gStencilFillPath) { + gStencilFillPath = (GrGLStencilFillPathProc)interface->fFunctions.fStencilFillPath; + } + if (NULL == gCoverFillPath) { + gCoverFillPath = (GrGLCoverFillPathProc)interface->fFunctions.fCoverFillPath; + } + if (NULL == gStencilStrokePath) { + gStencilStrokePath = (GrGLStencilStrokePathProc)interface->fFunctions.fStencilStrokePath; + } + if (NULL == gCoverStrokePath) { + gCoverStrokePath = (GrGLCoverStrokePathProc)interface->fFunctions.fCoverStrokePath; + } + if (NULL == gStencilFillPathInstanced) { + gStencilFillPathInstanced = (GrGLStencilFillPathInstancedProc) + interface->fFunctions.fStencilFillPathInstanced; + } + if (NULL == gCoverFillPathInstanced) { + gCoverFillPathInstanced = (GrGLCoverFillPathInstancedProc) + interface->fFunctions.fCoverFillPathInstanced; + } + if (NULL == gStencilStrokePathInstanced) { + gStencilStrokePathInstanced = (GrGLStencilStrokePathInstancedProc) + interface->fFunctions.fStencilStrokePathInstanced; + } + if (NULL == gCoverStrokePathInstanced) { + gCoverStrokePathInstanced = (GrGLCoverStrokePathInstancedProc) + interface->fFunctions.fCoverStrokePathInstanced; + } + + if (interface->fFunctions.fStencilFillPath != gStencilFillPath || + interface->fFunctions.fCoverFillPath != gCoverFillPath || + interface->fFunctions.fStencilStrokePath != gStencilStrokePath || + interface->fFunctions.fCoverStrokePath != gCoverStrokePath || + interface->fFunctions.fStencilFillPathInstanced != gStencilFillPathInstanced || + interface->fFunctions.fCoverFillPathInstanced != gCoverFillPathInstanced || + interface->fFunctions.fStencilStrokePathInstanced != gStencilStrokePathInstanced || + interface->fFunctions.fCoverStrokePathInstanced != gCoverStrokePathInstanced) { + // While not every windowing system requires GetProcAddress to return + // the same addresses in different contexts, it is guaranteed to do so + // in any context that supports NV_path_rendering. + SkFAIL("GetProcAddress returned different addresses for the same nvpr functions"); + return; + } + + interface->fFunctions.fStencilThenCoverFillPath = &stencil_then_cover_fill_path; + interface->fFunctions.fStencilThenCoverStrokePath = &stencil_then_cover_stroke_path; + interface->fFunctions.fStencilThenCoverFillPathInstanced = &stencil_then_cover_fill_path_instanced; + interface->fFunctions.fStencilThenCoverStrokePathInstanced = &stencil_then_cover_stroke_path_instanced; +} diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp index 823b73efa3..e9ba32ed24 100644 --- a/src/gpu/gl/GrGLInterface.cpp +++ b/src/gpu/gl/GrGLInterface.cpp @@ -467,7 +467,11 @@ bool GrGLInterface::validate() const { NULL == fFunctions.fCoverFillPath || NULL == fFunctions.fCoverStrokePath || NULL == fFunctions.fCoverFillPathInstanced || - NULL == fFunctions.fCoverStrokePathInstanced) { + NULL == fFunctions.fCoverStrokePathInstanced || + NULL == fFunctions.fStencilThenCoverFillPath || + NULL == fFunctions.fStencilThenCoverStrokePath || + NULL == fFunctions.fStencilThenCoverFillPathInstanced || + NULL == fFunctions.fStencilThenCoverStrokePathInstanced) { RETURN_FALSE_INTERFACE } // Currently ProgramPathFragmentInputGen is not used on diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index f079abce49..404e7abdbd 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -1894,20 +1894,23 @@ void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) { gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); - if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { - GL_CALL(StencilFillPath(id, fillMode, writeMask)); - } - if (stroke.needToApply()) { - GL_CALL(StencilStrokePath(id, 0xffff, writeMask)); - } - if (nonInvertedFill == fill) { if (stroke.needToApply()) { - GL_CALL(CoverStrokePath(id, GR_GL_BOUNDING_BOX)); + if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { + GL_CALL(StencilFillPath(id, fillMode, writeMask)); + } + GL_CALL(StencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX)); } else { - GL_CALL(CoverFillPath(id, GR_GL_BOUNDING_BOX)); + GL_CALL(StencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX)); } } else { + if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { + GL_CALL(StencilFillPath(id, fillMode, writeMask)); + } + if (stroke.needToApply()) { + GL_CALL(StencilStrokePath(id, 0xffff, writeMask)); + } + GrDrawState* drawState = this->drawState(); GrDrawState::AutoViewMatrixRestore avmr; SkRect bounds = SkRect::MakeLTRB(0, 0, @@ -1953,30 +1956,38 @@ void GrGpuGL::onGpuDrawPaths(const GrPathRange* pathRange, GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); - if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { - GL_CALL(StencilFillPathInstanced(count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, - writeMask, gXformType2GLType[transformsType], - transforms)); - } - if (stroke.needToApply()) { - GL_CALL(StencilStrokePathInstanced(count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, - writeMask, gXformType2GLType[transformsType], - transforms)); - } - if (nonInvertedFill == fill) { if (stroke.needToApply()) { - GL_CALL(CoverStrokePathInstanced( - count, GR_GL_UNSIGNED_INT, indices, baseID, + if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { + GL_CALL(StencilFillPathInstanced( + count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, + writeMask, gXformType2GLType[transformsType], + transforms)); + } + GL_CALL(StencilThenCoverStrokePathInstanced( + count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformsType], transforms)); } else { - GL_CALL(CoverFillPathInstanced( - count, GR_GL_UNSIGNED_INT, indices, baseID, + GL_CALL(StencilThenCoverFillPathInstanced( + count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, gXformType2GLType[transformsType], transforms)); } } else { + if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { + GL_CALL(StencilFillPathInstanced( + count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, + writeMask, gXformType2GLType[transformsType], + transforms)); + } + if (stroke.needToApply()) { + GL_CALL(StencilStrokePathInstanced( + count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, + writeMask, gXformType2GLType[transformsType], + transforms)); + } + GrDrawState* drawState = this->drawState(); GrDrawState::AutoViewMatrixRestore avmr; SkRect bounds = SkRect::MakeLTRB(0, 0, |