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" |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 return GrPathRendering::createGlyphs(typeface, NULL, stroke); | 145 return GrPathRendering::createGlyphs(typeface, NULL, stroke); |
146 } | 146 } |
147 | 147 |
148 // This is a crude approximation. We may want to consider giving this class | 148 // This is a crude approximation. We may want to consider giving this class |
149 // a pseudo PathGenerator whose sole purpose is to track the approximate gpu | 149 // a pseudo PathGenerator whose sole purpose is to track the approximate gpu |
150 // memory size. | 150 // memory size. |
151 const size_t gpuMemorySize = fontDataLength / 4; | 151 const size_t gpuMemorySize = fontDataLength / 4; |
152 return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize, stroke)); | 152 return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize, stroke)); |
153 } | 153 } |
154 | 154 |
155 void GrGLPathRendering::stencilPath(const GrPath* path, SkPath::FillType fill) { | 155 void GrGLPathRendering::stencilPath(const GrPath* path, const GrStencilSettings& stencilSettings) { |
156 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); | 156 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); |
157 SkASSERT(fGpu->drawState()->getRenderTarget()); | 157 SkASSERT(fGpu->drawState()->getRenderTarget()); |
158 SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer()); | 158 SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer()); |
159 | 159 |
160 this->flushPathStencilSettings(fill); | 160 this->flushPathStencilSettings(stencilSettings); |
161 SkASSERT(!fHWPathStencilSettings.isTwoSided()); | |
162 | |
163 GrGLenum fillMode = | |
164 gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.pass Op(GrStencilSettings::kFront_Face)); | |
165 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFro nt_Face); | |
166 GL_CALL(StencilFillPath(id, fillMode, writeMask)); | |
167 } | |
168 | |
169 void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) { | |
170 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); | |
171 SkASSERT(fGpu->drawState()->getRenderTarget()); | |
172 SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer()); | |
173 | |
174 this->flushPathStencilSettings(fill); | |
175 SkASSERT(!fHWPathStencilSettings.isTwoSided()); | 161 SkASSERT(!fHWPathStencilSettings.isTwoSided()); |
176 | 162 |
177 const SkStrokeRec& stroke = path->getStroke(); | 163 const SkStrokeRec& stroke = path->getStroke(); |
178 | 164 |
179 SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(fill) ; | |
180 | |
181 GrGLenum fillMode = | 165 GrGLenum fillMode = |
182 gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.pass Op(GrStencilSettings::kFront_Face)); | 166 gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.pass Op(GrStencilSettings::kFront_Face)); |
183 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFro nt_Face); | 167 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFro nt_Face); |
184 | 168 |
185 if (nonInvertedFill == fill) { | 169 if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getS tyle()) { |
Kimmo Kinnunen
2014/11/03 20:39:12
So I guess this is not part of "refactoring", rath
joshualitt
2014/11/03 20:51:46
Err, is there a problem with this chunk? The orig
| |
186 if (stroke.needToApply()) { | 170 GL_CALL(StencilFillPath(id, fillMode, writeMask)); |
187 if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { | 171 } |
188 GL_CALL(StencilFillPath(id, fillMode, writeMask)); | 172 if (stroke.needToApply()) { |
189 } | 173 GL_CALL(StencilStrokePath(id, 0xffff, writeMask)); |
190 this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDI NG_BOX); | 174 } |
191 } else { | 175 } |
192 this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDI NG_BOX); | 176 |
193 } | 177 void GrGLPathRendering::drawPath(const GrPath* path, const GrStencilSettings& st encilSettings) { |
194 } else { | 178 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); |
195 if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke. getStyle()) { | 179 SkASSERT(fGpu->drawState()->getRenderTarget()); |
180 SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer()); | |
181 | |
182 this->flushPathStencilSettings(stencilSettings); | |
183 SkASSERT(!fHWPathStencilSettings.isTwoSided()); | |
184 | |
185 const SkStrokeRec& stroke = path->getStroke(); | |
186 | |
187 GrGLenum fillMode = | |
188 gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.pass Op(GrStencilSettings::kFront_Face)); | |
189 GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFro nt_Face); | |
190 | |
191 if (stroke.needToApply()) { | |
192 if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { | |
196 GL_CALL(StencilFillPath(id, fillMode, writeMask)); | 193 GL_CALL(StencilFillPath(id, fillMode, writeMask)); |
197 } | 194 } |
198 if (stroke.needToApply()) { | 195 this->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_B OX); |
199 GL_CALL(StencilStrokePath(id, 0xffff, writeMask)); | 196 } else { |
200 } | 197 this->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_B OX); |
201 | |
202 GrDrawState* drawState = fGpu->drawState(); | |
203 GrDrawState::AutoViewMatrixRestore avmr; | |
204 SkRect bounds = SkRect::MakeLTRB(0, 0, | |
205 SkIntToScalar(drawState->getRenderTarge t()->width()), | |
206 SkIntToScalar(drawState->getRenderTarge t()->height())); | |
207 SkMatrix vmi; | |
208 // mapRect through persp matrix may not be correct | |
209 if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewIn verse(&vmi)) { | |
210 vmi.mapRect(&bounds); | |
211 // theoretically could set bloat = 0, instead leave it because of ma trix inversion | |
212 // precision. | |
213 SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_Scala rHalf; | |
214 bounds.outset(bloat, bloat); | |
215 } else { | |
216 avmr.setIdentity(drawState); | |
217 } | |
218 | |
219 fGpu->drawSimpleRect(bounds); | |
220 } | 198 } |
221 } | 199 } |
222 | 200 |
223 void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t i ndices[], int count, | 201 void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t i ndices[], int count, |
224 const float transforms[], PathTransformType tr ansformsType, | 202 const float transforms[], PathTransformType tr ansformsType, |
225 SkPath::FillType fill) { | 203 const GrStencilSettings& stencilSettings) { |
226 SkASSERT(fGpu->caps()->pathRenderingSupport()); | 204 SkASSERT(fGpu->caps()->pathRenderingSupport()); |
227 SkASSERT(fGpu->drawState()->getRenderTarget()); | 205 SkASSERT(fGpu->drawState()->getRenderTarget()); |
228 SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer()); | 206 SkASSERT(fGpu->drawState()->getRenderTarget()->getStencilBuffer()); |
229 | 207 |
230 GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID() ; | 208 GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID() ; |
231 | 209 |
232 this->flushPathStencilSettings(fill); | 210 this->flushPathStencilSettings(stencilSettings); |
233 SkASSERT(!fHWPathStencilSettings.isTwoSided()); | 211 SkASSERT(!fHWPathStencilSettings.isTwoSided()); |
234 | 212 |
235 const SkStrokeRec& stroke = pathRange->getStroke(); | 213 const SkStrokeRec& stroke = pathRange->getStroke(); |
236 | 214 |
237 SkPath::FillType nonInvertedFill = | |
238 SkPath::ConvertToNonInverseFillType(fill); | |
239 | |
240 GrGLenum fillMode = | 215 GrGLenum fillMode = |
241 gr_stencil_op_to_gl_path_rendering_fill_mode( | 216 gr_stencil_op_to_gl_path_rendering_fill_mode( |
242 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); | 217 fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); |
243 GrGLint writeMask = | 218 GrGLint writeMask = |
244 fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); | 219 fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); |
245 | 220 |
246 if (nonInvertedFill == fill) { | 221 if (stroke.needToApply()) { |
247 if (stroke.needToApply()) { | 222 if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { |
248 if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) { | 223 GL_CALL(StencilFillPathInstanced( |
249 GL_CALL(StencilFillPathInstanced( | 224 count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode , |
250 count, GR_GL_UNSIGNED_INT, indices, baseID, fill Mode, | 225 writeMask, gXformType2GLType[transformsType], |
251 writeMask, gXformType2GLType[transformsType], | 226 transforms)); |
252 transforms)); | |
253 } | |
254 this->stencilThenCoverStrokePathInstanced( | |
255 count, GR_GL_UNSIGNED_INT, indices, baseID, 0xff ff, writeMask, | |
256 GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, | |
257 gXformType2GLType[transformsType], transforms); | |
258 } else { | |
259 this->stencilThenCoverFillPathInstanced( | |
260 count, GR_GL_UNSIGNED_INT, indices, baseID, fill Mode, writeMask, | |
261 GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, | |
262 gXformType2GLType[transformsType], transforms); | |
263 } | 227 } |
228 this->stencilThenCoverStrokePathInstanced( | |
229 count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask, | |
230 GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, | |
231 gXformType2GLType[transformsType], transforms); | |
264 } else { | 232 } else { |
265 if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke. getStyle()) { | 233 this->stencilThenCoverFillPathInstanced( |
266 GL_CALL(StencilFillPathInstanced( | 234 count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode , writeMask, |
267 count, GR_GL_UNSIGNED_INT, indices, baseID, fill Mode, | 235 GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES, |
268 writeMask, gXformType2GLType[transformsType], | 236 gXformType2GLType[transformsType], transforms); |
269 transforms)); | |
270 } | |
271 if (stroke.needToApply()) { | |
272 GL_CALL(StencilStrokePathInstanced( | |
273 count, GR_GL_UNSIGNED_INT, indices, baseID, 0xff ff, | |
274 writeMask, gXformType2GLType[transformsType], | |
275 transforms)); | |
276 } | |
277 | |
278 GrDrawState* drawState = fGpu->drawState(); | |
279 GrDrawState::AutoViewMatrixRestore avmr; | |
280 SkRect bounds = SkRect::MakeLTRB(0, 0, | |
281 SkIntToScalar(drawState->getRenderTarge t()->width()), | |
282 SkIntToScalar(drawState->getRenderTarge t()->height())); | |
283 SkMatrix vmi; | |
284 // mapRect through persp matrix may not be correct | |
285 if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewIn verse(&vmi)) { | |
286 vmi.mapRect(&bounds); | |
287 // theoretically could set bloat = 0, instead leave it because of ma trix inversion | |
288 // precision. | |
289 SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_Scala rHalf; | |
290 bounds.outset(bloat, bloat); | |
291 } else { | |
292 avmr.setIdentity(drawState); | |
293 } | |
294 | |
295 fGpu->drawSimpleRect(bounds); | |
296 } | 237 } |
297 } | 238 } |
298 | 239 |
299 void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents compo nents, | 240 void GrGLPathRendering::enablePathTexGen(int unitIdx, PathTexGenComponents compo nents, |
300 const GrGLfloat* coefficients) { | 241 const GrGLfloat* coefficients) { |
301 SkASSERT(components >= kS_PathTexGenComponents && | 242 SkASSERT(components >= kS_PathTexGenComponents && |
302 components <= kSTR_PathTexGenComponents); | 243 components <= kSTR_PathTexGenComponents); |
303 SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= unitIdx); | 244 SkASSERT(fGpu->glCaps().maxFixedFunctionTextureCoords() >= unitIdx); |
304 | 245 |
305 if (GR_GL_OBJECT_LINEAR == fHWPathTexGenSettings[unitIdx].fMode && | 246 if (GR_GL_OBJECT_LINEAR == fHWPathTexGenSettings[unitIdx].fMode && |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 // generated by the GenPaths fallback (or else was never allocated). | 400 // generated by the GenPaths fallback (or else was never allocated). |
460 GL_CALL(DeletePaths(path, 1)); | 401 GL_CALL(DeletePaths(path, 1)); |
461 return; | 402 return; |
462 } | 403 } |
463 | 404 |
464 // Make the path empty to save memory, but don't free the name in the driver . | 405 // Make the path empty to save memory, but don't free the name in the driver . |
465 GL_CALL(PathCommands(path, 0, NULL, 0, GR_GL_FLOAT, NULL)); | 406 GL_CALL(PathCommands(path, 0, NULL, 0, GR_GL_FLOAT, NULL)); |
466 fPathNameAllocator->free(path); | 407 fPathNameAllocator->free(path); |
467 } | 408 } |
468 | 409 |
469 void GrGLPathRendering::flushPathStencilSettings(SkPath::FillType fill) { | 410 void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stenci lSettings) { |
470 GrStencilSettings pathStencilSettings; | 411 if (fHWPathStencilSettings != stencilSettings) { |
471 fGpu->getPathStencilSettingsForFillType(fill, &pathStencilSettings); | |
472 if (fHWPathStencilSettings != pathStencilSettings) { | |
473 // Just the func, ref, and mask is set here. The op and write mask are p arams to the call | 412 // Just the func, ref, and mask is set here. The op and write mask are p arams to the call |
474 // that draws the path to the SB (glStencilFillPath) | 413 // that draws the path to the SB (glStencilFillPath) |
475 GrGLenum func = | 414 GrGLenum func = |
476 GrToGLStencilFunc(pathStencilSettings.func(GrStencilSettings::kFront _Face)); | 415 GrToGLStencilFunc(stencilSettings.func(GrStencilSettings::kFront_Fac e)); |
477 GL_CALL(PathStencilFunc(func, pathStencilSettings.funcRef(GrStencilSetti ngs::kFront_Face), | 416 GL_CALL(PathStencilFunc(func, stencilSettings.funcRef(GrStencilSettings: :kFront_Face), |
478 pathStencilSettings.funcMask(GrStencilSettings:: kFront_Face))); | 417 stencilSettings.funcMask(GrStencilSettings::kFro nt_Face))); |
479 | 418 |
480 fHWPathStencilSettings = pathStencilSettings; | 419 fHWPathStencilSettings = stencilSettings; |
481 } | 420 } |
482 } | 421 } |
483 | 422 |
484 inline void GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode, | 423 inline void GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode, |
485 GrGLuint mask, GrGLenum cov erMode) { | 424 GrGLuint mask, GrGLenum cov erMode) { |
486 if (caps().stencilThenCoverSupport) { | 425 if (caps().stencilThenCoverSupport) { |
487 GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode)); | 426 GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode)); |
488 return; | 427 return; |
489 } | 428 } |
490 GL_CALL(StencilFillPath(path, fillMode, mask)); | 429 GL_CALL(StencilFillPath(path, fillMode, mask)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
525 reference, mask, coverMode, transformType, | 464 reference, mask, coverMode, transformType, |
526 transformValues)); | 465 transformValues)); |
527 return; | 466 return; |
528 } | 467 } |
529 | 468 |
530 GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, | 469 GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, |
531 reference, mask, transformType, transform Values)); | 470 reference, mask, transformType, transform Values)); |
532 GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, | 471 GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, |
533 coverMode, transformType, transformValues)) ; | 472 coverMode, transformType, transformValues)) ; |
534 } | 473 } |
OLD | NEW |