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 |