| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 #include "gl/GrGLPathRendering.h" | 8 #include "gl/GrGLPathRendering.h" |
| 9 #include "gl/GrGLNameAllocator.h" | 9 #include "gl/GrGLNameAllocator.h" |
| 10 #include "gl/GrGLUtil.h" | 10 #include "gl/GrGLUtil.h" |
| 11 #include "gl/GrGLGpu.h" | 11 #include "gl/GrGLGpu.h" |
| 12 | 12 |
| 13 #include "GrGLPath.h" | 13 #include "GrGLPath.h" |
| 14 #include "GrGLPathRange.h" | 14 #include "GrGLPathRange.h" |
| 15 #include "GrGLPathRendering.h" | 15 #include "GrGLPathRendering.h" |
| 16 | 16 |
| 17 #include "SkStream.h" | 17 #include "SkStream.h" |
| 18 #include "SkTypeface.h" | 18 #include "SkTypeface.h" |
| 19 | 19 |
| 20 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) | 20 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) |
| 21 #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(fGpu->glInterface(), RET, X) | 21 #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->gpu()->glInterface(), RET, X) |
| 22 | 22 |
| 23 | 23 |
| 24 static const GrGLenum gIndexType2GLType[] = { | 24 static const GrGLenum gIndexType2GLType[] = { |
| 25 GR_GL_UNSIGNED_BYTE, | 25 GR_GL_UNSIGNED_BYTE, |
| 26 GR_GL_UNSIGNED_SHORT, | 26 GR_GL_UNSIGNED_SHORT, |
| 27 GR_GL_UNSIGNED_INT | 27 GR_GL_UNSIGNED_INT |
| 28 }; | 28 }; |
| 29 | 29 |
| 30 GR_STATIC_ASSERT(0 == GrPathRange::kU8_PathIndexType); | 30 GR_STATIC_ASSERT(0 == GrPathRange::kU8_PathIndexType); |
| 31 GR_STATIC_ASSERT(1 == GrPathRange::kU16_PathIndexType); | 31 GR_STATIC_ASSERT(1 == GrPathRange::kU16_PathIndexType); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 53 SkFAIL("Unexpected path fill."); | 53 SkFAIL("Unexpected path fill."); |
| 54 /* fallthrough */; | 54 /* fallthrough */; |
| 55 case kIncClamp_StencilOp: | 55 case kIncClamp_StencilOp: |
| 56 return GR_GL_COUNT_UP; | 56 return GR_GL_COUNT_UP; |
| 57 case kInvert_StencilOp: | 57 case kInvert_StencilOp: |
| 58 return GR_GL_INVERT; | 58 return GR_GL_INVERT; |
| 59 } | 59 } |
| 60 } | 60 } |
| 61 | 61 |
| 62 GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu) | 62 GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu) |
| 63 : fGpu(gpu) { | 63 : GrPathRendering(gpu) { |
| 64 const GrGLInterface* glInterface = gpu->glInterface(); | 64 const GrGLInterface* glInterface = gpu->glInterface(); |
| 65 fCaps.stencilThenCoverSupport = | 65 fCaps.stencilThenCoverSupport = |
| 66 NULL != glInterface->fFunctions.fStencilThenCoverFillPath && | 66 NULL != glInterface->fFunctions.fStencilThenCoverFillPath && |
| 67 NULL != glInterface->fFunctions.fStencilThenCoverStrokePath && | 67 NULL != glInterface->fFunctions.fStencilThenCoverStrokePath && |
| 68 NULL != glInterface->fFunctions.fStencilThenCoverFillPathInstanced && | 68 NULL != glInterface->fFunctions.fStencilThenCoverFillPathInstanced && |
| 69 NULL != glInterface->fFunctions.fStencilThenCoverStrokePathInstanced; | 69 NULL != glInterface->fFunctions.fStencilThenCoverStrokePathInstanced; |
| 70 fCaps.fragmentInputGenSupport = | 70 fCaps.fragmentInputGenSupport = |
| 71 NULL != glInterface->fFunctions.fProgramPathFragmentInputGen; | 71 NULL != glInterface->fFunctions.fProgramPathFragmentInputGen; |
| 72 fCaps.glyphLoadingSupport = | 72 fCaps.glyphLoadingSupport = |
| 73 NULL != glInterface->fFunctions.fPathMemoryGlyphIndexArray; | 73 NULL != glInterface->fFunctions.fPathMemoryGlyphIndexArray; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 85 void GrGLPathRendering::resetContext() { | 85 void GrGLPathRendering::resetContext() { |
| 86 fHWProjectionMatrixState.invalidate(); | 86 fHWProjectionMatrixState.invalidate(); |
| 87 // we don't use the model view matrix. | 87 // we don't use the model view matrix. |
| 88 GL_CALL(MatrixLoadIdentity(GR_GL_PATH_MODELVIEW)); | 88 GL_CALL(MatrixLoadIdentity(GR_GL_PATH_MODELVIEW)); |
| 89 | 89 |
| 90 SkASSERT(fCaps.fragmentInputGenSupport); | 90 SkASSERT(fCaps.fragmentInputGenSupport); |
| 91 fHWPathStencilSettings.invalidate(); | 91 fHWPathStencilSettings.invalidate(); |
| 92 } | 92 } |
| 93 | 93 |
| 94 GrPath* GrGLPathRendering::createPath(const SkPath& inPath, const GrStrokeInfo&
stroke) { | 94 GrPath* GrGLPathRendering::createPath(const SkPath& inPath, const GrStrokeInfo&
stroke) { |
| 95 return SkNEW_ARGS(GrGLPath, (fGpu, inPath, stroke)); | 95 return SkNEW_ARGS(GrGLPath, (this->gpu(), inPath, stroke)); |
| 96 } | 96 } |
| 97 | 97 |
| 98 GrPathRange* GrGLPathRendering::createPathRange(GrPathRange::PathGenerator* path
Generator, | 98 GrPathRange* GrGLPathRendering::createPathRange(GrPathRange::PathGenerator* path
Generator, |
| 99 const GrStrokeInfo& stroke) { | 99 const GrStrokeInfo& stroke) { |
| 100 return SkNEW_ARGS(GrGLPathRange, (fGpu, pathGenerator, stroke)); | 100 return SkNEW_ARGS(GrGLPathRange, (this->gpu(), pathGenerator, stroke)); |
| 101 } | 101 } |
| 102 | 102 |
| 103 GrPathRange* GrGLPathRendering::createGlyphs(const SkTypeface* typeface, | 103 GrPathRange* GrGLPathRendering::createGlyphs(const SkTypeface* typeface, |
| 104 const SkDescriptor* desc, | 104 const SkDescriptor* desc, |
| 105 const GrStrokeInfo& stroke) { | 105 const GrStrokeInfo& stroke) { |
| 106 if (NULL != desc || !caps().glyphLoadingSupport || stroke.isDashed()) { | 106 if (NULL != desc || !caps().glyphLoadingSupport || stroke.isDashed()) { |
| 107 return GrPathRendering::createGlyphs(typeface, desc, stroke); | 107 return GrPathRendering::createGlyphs(typeface, desc, stroke); |
| 108 } | 108 } |
| 109 | 109 |
| 110 if (NULL == typeface) { | 110 if (NULL == typeface) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 126 // TODO: Find a more efficient way to pass the font data (e.g. open file
descriptor). | 126 // TODO: Find a more efficient way to pass the font data (e.g. open file
descriptor). |
| 127 fontTempBuffer.reset(SkToInt(fontDataLength)); | 127 fontTempBuffer.reset(SkToInt(fontDataLength)); |
| 128 fontStream->read(&fontTempBuffer.front(), fontDataLength); | 128 fontStream->read(&fontTempBuffer.front(), fontDataLength); |
| 129 fontData = &fontTempBuffer.front(); | 129 fontData = &fontTempBuffer.front(); |
| 130 } | 130 } |
| 131 | 131 |
| 132 const int numPaths = typeface->countGlyphs(); | 132 const int numPaths = typeface->countGlyphs(); |
| 133 const GrGLuint basePathID = this->genPaths(numPaths); | 133 const GrGLuint basePathID = this->genPaths(numPaths); |
| 134 | 134 |
| 135 // Init the basePathID as the template path. | 135 // Init the basePathID as the template path. |
| 136 GrGLPath::InitPathObject(fGpu, basePathID, SkPath(), stroke); | 136 GrGLPath::InitPathObject(this->gpu(), basePathID, SkPath(), stroke); |
| 137 | 137 |
| 138 GrGLenum status; | 138 GrGLenum status; |
| 139 GL_CALL_RET(status, PathMemoryGlyphIndexArray(basePathID, GR_GL_STANDARD_FON
T_FORMAT, | 139 GL_CALL_RET(status, PathMemoryGlyphIndexArray(basePathID, GR_GL_STANDARD_FON
T_FORMAT, |
| 140 fontDataLength, fontData, face
Index, 0, | 140 fontDataLength, fontData, face
Index, 0, |
| 141 numPaths, basePathID, | 141 numPaths, basePathID, |
| 142 SkPaint::kCanonicalTextSizeFor
Paths)); | 142 SkPaint::kCanonicalTextSizeFor
Paths)); |
| 143 | 143 |
| 144 if (GR_GL_FONT_GLYPHS_AVAILABLE != status) { | 144 if (GR_GL_FONT_GLYPHS_AVAILABLE != status) { |
| 145 this->deletePaths(basePathID, numPaths); | 145 this->deletePaths(basePathID, numPaths); |
| 146 return GrPathRendering::createGlyphs(typeface, NULL, stroke); | 146 return GrPathRendering::createGlyphs(typeface, NULL, stroke); |
| 147 } | 147 } |
| 148 | 148 |
| 149 // This is a crude approximation. We may want to consider giving this class | 149 // This is a crude approximation. We may want to consider giving this class |
| 150 // a pseudo PathGenerator whose sole purpose is to track the approximate gpu | 150 // a pseudo PathGenerator whose sole purpose is to track the approximate gpu |
| 151 // memory size. | 151 // memory size. |
| 152 const size_t gpuMemorySize = fontDataLength / 4; | 152 const size_t gpuMemorySize = fontDataLength / 4; |
| 153 return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize,
stroke)); | 153 return SkNEW_ARGS(GrGLPathRange, (this->gpu(), basePathID, numPaths, gpuMemo
rySize, stroke)); |
| 154 } | 154 } |
| 155 | 155 |
| 156 void GrGLPathRendering::stencilPath(const GrPath* path, const GrStencilSettings&
stencilSettings) { | 156 void GrGLPathRendering::onStencilPath(const StencilPathArgs& args, const GrPath*
path) { |
| 157 GrGLGpu* gpu = this->gpu(); |
| 158 SkASSERT(gpu->caps()->shaderCaps()->pathRenderingSupport()); |
| 159 gpu->flushColorWrite(false); |
| 160 gpu->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace); |
| 161 |
| 162 GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(args.fRenderTarget); |
| 163 SkISize size = SkISize::Make(rt->width(), rt->height()); |
| 164 this->setProjectionMatrix(*args.fViewMatrix, size, rt->origin()); |
| 165 gpu->flushScissor(*args.fScissor, rt->getViewport(), rt->origin()); |
| 166 gpu->flushHWAAState(rt, args.fUseHWAA); |
| 167 gpu->flushRenderTarget(rt, NULL); |
| 168 |
| 157 const GrGLPath* glPath = static_cast<const GrGLPath*>(path); | 169 const GrGLPath* glPath = static_cast<const GrGLPath*>(path); |
| 158 | 170 |
| 159 this->flushPathStencilSettings(stencilSettings); | 171 this->flushPathStencilSettings(*args.fStencil); |
| 160 SkASSERT(!fHWPathStencilSettings.isTwoSided()); | 172 SkASSERT(!fHWPathStencilSettings.isTwoSided()); |
| 161 | 173 |
| 162 GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( | 174 GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( |
| 163 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); | 175 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); |
| 164 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFro
nt_Face); | 176 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFro
nt_Face); |
| 165 | 177 |
| 166 if (glPath->shouldFill()) { | 178 if (glPath->shouldFill()) { |
| 167 GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask)); | 179 GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask)); |
| 168 } | 180 } |
| 169 if (glPath->shouldStroke()) { | 181 if (glPath->shouldStroke()) { |
| 170 GL_CALL(StencilStrokePath(glPath->pathID(), 0xffff, writeMask)); | 182 GL_CALL(StencilStrokePath(glPath->pathID(), 0xffff, writeMask)); |
| 171 } | 183 } |
| 172 } | 184 } |
| 173 | 185 |
| 174 void GrGLPathRendering::drawPath(const GrPath* path, const GrStencilSettings& st
encilSettings) { | 186 void GrGLPathRendering::onDrawPath(const DrawPathArgs& args, const GrPath* path)
{ |
| 187 if (!this->gpu()->flushGLState(args)) { |
| 188 return; |
| 189 } |
| 175 const GrGLPath* glPath = static_cast<const GrGLPath*>(path); | 190 const GrGLPath* glPath = static_cast<const GrGLPath*>(path); |
| 176 | 191 |
| 177 this->flushPathStencilSettings(stencilSettings); | 192 this->flushPathStencilSettings(*args.fStencil); |
| 178 SkASSERT(!fHWPathStencilSettings.isTwoSided()); | 193 SkASSERT(!fHWPathStencilSettings.isTwoSided()); |
| 179 | 194 |
| 180 GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( | 195 GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( |
| 181 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); | 196 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); |
| 182 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFro
nt_Face); | 197 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFro
nt_Face); |
| 183 | 198 |
| 184 if (glPath->shouldStroke()) { | 199 if (glPath->shouldStroke()) { |
| 185 if (glPath->shouldFill()) { | 200 if (glPath->shouldFill()) { |
| 186 GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask)); | 201 GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask)); |
| 187 } | 202 } |
| 188 this->stencilThenCoverStrokePath(glPath->pathID(), 0xffff, writeMask, GR
_GL_BOUNDING_BOX); | 203 this->stencilThenCoverStrokePath(glPath->pathID(), 0xffff, writeMask, GR
_GL_BOUNDING_BOX); |
| 189 } else { | 204 } else { |
| 190 this->stencilThenCoverFillPath(glPath->pathID(), fillMode, writeMask, GR
_GL_BOUNDING_BOX); | 205 this->stencilThenCoverFillPath(glPath->pathID(), fillMode, writeMask, GR
_GL_BOUNDING_BOX); |
| 191 } | 206 } |
| 192 } | 207 } |
| 193 | 208 |
| 194 void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, | 209 void GrGLPathRendering::onDrawPaths(const DrawPathArgs& args, const GrPathRange*
pathRange, |
| 195 const void* indices, PathIndexType indexType, | 210 const void* indices, PathIndexType indexType
, |
| 196 const float transformValues[], PathTransformTy
pe transformType, | 211 const float transformValues[], PathTransform
Type transformType, |
| 197 int count, const GrStencilSettings& stencilSet
tings) { | 212 int count) { |
| 198 SkASSERT(fGpu->caps()->shaderCaps()->pathRenderingSupport()); | 213 if (!this->gpu()->flushGLState(args)) { |
| 214 return; |
| 215 } |
| 216 this->flushPathStencilSettings(*args.fStencil); |
| 217 SkASSERT(!fHWPathStencilSettings.isTwoSided()); |
| 218 |
| 199 | 219 |
| 200 const GrGLPathRange* glPathRange = static_cast<const GrGLPathRange*>(pathRan
ge); | 220 const GrGLPathRange* glPathRange = static_cast<const GrGLPathRange*>(pathRan
ge); |
| 201 | 221 |
| 202 this->flushPathStencilSettings(stencilSettings); | |
| 203 SkASSERT(!fHWPathStencilSettings.isTwoSided()); | |
| 204 | |
| 205 GrGLenum fillMode = | 222 GrGLenum fillMode = |
| 206 gr_stencil_op_to_gl_path_rendering_fill_mode( | 223 gr_stencil_op_to_gl_path_rendering_fill_mode( |
| 207 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); | 224 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); |
| 208 GrGLint writeMask = | 225 GrGLint writeMask = |
| 209 fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); | 226 fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); |
| 210 | 227 |
| 211 if (glPathRange->shouldStroke()) { | 228 if (glPathRange->shouldStroke()) { |
| 212 if (glPathRange->shouldFill()) { | 229 if (glPathRange->shouldFill()) { |
| 213 GL_CALL(StencilFillPathInstanced( | 230 GL_CALL(StencilFillPathInstanced( |
| 214 count, gIndexType2GLType[indexType], indices, glPath
Range->basePathID(), | 231 count, gIndexType2GLType[indexType], indices, glPath
Range->basePathID(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]); | 267 coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]); |
| 251 } | 268 } |
| 252 | 269 |
| 253 GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components,
coefficients)); | 270 GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components,
coefficients)); |
| 254 } | 271 } |
| 255 | 272 |
| 256 void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix, | 273 void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix, |
| 257 const SkISize& renderTargetSize, | 274 const SkISize& renderTargetSize, |
| 258 GrSurfaceOrigin renderTargetOrigin)
{ | 275 GrSurfaceOrigin renderTargetOrigin)
{ |
| 259 | 276 |
| 260 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport()); | 277 SkASSERT(this->gpu()->glCaps().shaderCaps()->pathRenderingSupport()); |
| 261 | 278 |
| 262 if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin && | 279 if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin && |
| 263 renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize && | 280 renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize && |
| 264 matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) { | 281 matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) { |
| 265 return; | 282 return; |
| 266 } | 283 } |
| 267 | 284 |
| 268 fHWProjectionMatrixState.fViewMatrix = matrix; | 285 fHWProjectionMatrixState.fViewMatrix = matrix; |
| 269 fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize; | 286 fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize; |
| 270 fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin; | 287 fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 reference, mask, coverMode,
transformType, | 399 reference, mask, coverMode,
transformType, |
| 383 transformValues)); | 400 transformValues)); |
| 384 return; | 401 return; |
| 385 } | 402 } |
| 386 | 403 |
| 387 GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, | 404 GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, |
| 388 reference, mask, transformType, transform
Values)); | 405 reference, mask, transformType, transform
Values)); |
| 389 GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, | 406 GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, |
| 390 coverMode, transformType, transformValues))
; | 407 coverMode, transformType, transformValues))
; |
| 391 } | 408 } |
| 409 |
| 410 inline GrGLGpu* GrGLPathRendering::gpu() { |
| 411 return static_cast<GrGLGpu*>(fGpu); |
| 412 } |
| OLD | NEW |