Chromium Code Reviews| 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()) { |
| 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 = | |
|
bsalomon
2014/10/30 20:11:01
I realize you're not done and using StencilSetting
joshualitt
2014/10/30 21:24:33
Yea, I promise I will come back and work on this s
| |
| 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 |