Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "GrDefaultPathRenderer.h" | 8 #include "GrDefaultPathRenderer.h" |
| 9 | 9 |
| 10 #include "GrBatch.h" | |
| 11 #include "GrBatchTarget.h" | |
| 12 #include "GrBufferAllocPool.h" | |
| 10 #include "GrContext.h" | 13 #include "GrContext.h" |
| 11 #include "GrDefaultGeoProcFactory.h" | 14 #include "GrDefaultGeoProcFactory.h" |
| 12 #include "GrPathUtils.h" | 15 #include "GrPathUtils.h" |
| 13 #include "GrPipelineBuilder.h" | 16 #include "GrPipelineBuilder.h" |
| 14 #include "SkGeometry.h" | 17 #include "SkGeometry.h" |
| 15 #include "SkString.h" | 18 #include "SkString.h" |
| 16 #include "SkStrokeRec.h" | 19 #include "SkStrokeRec.h" |
| 17 #include "SkTLazy.h" | 20 #include "SkTLazy.h" |
| 18 #include "SkTraceEvent.h" | 21 #include "SkTraceEvent.h" |
| 19 | 22 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 // drawing triangle fans around fanCenterIdx. | 187 // drawing triangle fans around fanCenterIdx. |
| 185 if (!hairLine) { | 188 if (!hairLine) { |
| 186 *((*indices)++) = fanCenterIdx; | 189 *((*indices)++) = fanCenterIdx; |
| 187 } | 190 } |
| 188 *((*indices)++) = edgeV0Idx; | 191 *((*indices)++) = edgeV0Idx; |
| 189 *((*indices)++) = edgeV0Idx + 1; | 192 *((*indices)++) = edgeV0Idx + 1; |
| 190 } | 193 } |
| 191 | 194 |
| 192 static inline void add_quad(SkPoint** vert, const SkPoint* base, const SkPoint p ts[], | 195 static inline void add_quad(SkPoint** vert, const SkPoint* base, const SkPoint p ts[], |
| 193 SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol, bool indexed, | 196 SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol, bool indexed, |
| 194 bool isHairline, uint16_t subpathIdxStart, uint16_t* * idx) { | 197 bool isHairline, uint16_t subpathIdxStart, int offse t, uint16_t** idx) { |
| 195 // first pt of quad is the pt we ended on in previous step | 198 // first pt of quad is the pt we ended on in previous step |
| 196 uint16_t firstQPtIdx = (uint16_t)(*vert - base) - 1; | 199 uint16_t firstQPtIdx = (uint16_t)(*vert - base) - 1 + offset; |
| 197 uint16_t numPts = (uint16_t) | 200 uint16_t numPts = (uint16_t) |
| 198 GrPathUtils::generateQuadraticPoints( | 201 GrPathUtils::generateQuadraticPoints( |
| 199 pts[0], pts[1], pts[2], | 202 pts[0], pts[1], pts[2], |
| 200 srcSpaceTolSqd, vert, | 203 srcSpaceTolSqd, vert, |
| 201 GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); | 204 GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); |
| 202 if (indexed) { | 205 if (indexed) { |
| 203 for (uint16_t i = 0; i < numPts; ++i) { | 206 for (uint16_t i = 0; i < numPts; ++i) { |
| 204 append_countour_edge_indices(isHairline, subpathIdxStart, | 207 append_countour_edge_indices(isHairline, subpathIdxStart, |
| 205 firstQPtIdx + i, idx); | 208 firstQPtIdx + i, idx); |
| 206 } | 209 } |
| 207 } | 210 } |
| 208 } | 211 } |
| 209 | 212 |
| 210 bool GrDefaultPathRenderer::createGeom(GrDrawTarget* target, | 213 class DefaultPathBatch : public GrBatch { |
| 211 GrPipelineBuilder* pipelineBuilder, | 214 public: |
| 212 GrPrimitiveType* primType, | 215 struct Geometry { |
| 213 int* vertexCnt, | 216 GrColor fColor; |
| 214 int* indexCnt, | 217 SkPath fPath; |
| 215 GrDrawTarget::AutoReleaseGeometry* arg, | 218 SkScalar fTolerance; |
| 216 const SkPath& path, | 219 SkDEBUGCODE(SkRect fDevBounds;) |
| 217 const SkStrokeRec& stroke, | 220 }; |
| 218 SkScalar srcSpaceTol) { | 221 |
| 219 { | 222 static GrBatch* Create(const Geometry& geometry, uint8_t coverage, const SkM atrix& viewMatrix, |
| 220 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol); | 223 bool isHairline) { |
| 221 int contourCnt; | 224 return SkNEW_ARGS(DefaultPathBatch, (geometry, coverage, viewMatrix, isH airline)); |
| 222 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, | 225 } |
| 223 srcSpaceTol); | 226 |
| 224 | 227 const char* name() const SK_OVERRIDE { return "DefaultPathBatch"; } |
| 225 if (maxPts <= 0) { | 228 |
| 226 return false; | 229 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { |
| 227 } | 230 // When this is called on a batch, there is only one geometry bundle |
| 228 if (maxPts > ((int)SK_MaxU16 + 1)) { | 231 out->setKnownFourComponents(fGeoData[0].fColor); |
| 229 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); | 232 } |
| 230 return false; | 233 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E { |
| 231 } | 234 out->setUnknownSingleComponent(); |
| 232 | 235 } |
| 233 bool indexed = contourCnt > 1; | 236 |
| 234 | 237 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { |
| 235 const bool isHairline = stroke.isHairlineStyle(); | 238 // Handle any color overrides |
| 236 | 239 if (init.fColorIgnored) { |
| 237 int maxIdxs = 0; | 240 fGeoData[0].fColor = GrColor_ILLEGAL; |
| 238 if (isHairline) { | 241 } else if (GrColor_ILLEGAL != init.fOverrideColor) { |
| 239 if (indexed) { | 242 fGeoData[0].fColor = init.fOverrideColor; |
| 240 maxIdxs = 2 * maxPts; | 243 } |
| 241 *primType = kLines_GrPrimitiveType; | 244 |
| 245 // setup batch properties | |
| 246 fBatch.fColorIgnored = init.fColorIgnored; | |
| 247 fBatch.fColor = fGeoData[0].fColor; | |
| 248 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; | |
| 249 fBatch.fCoverageIgnored = init.fCoverageIgnored; | |
| 250 } | |
| 251 | |
| 252 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE { | |
| 253 SkAutoTUnref<const GrGeometryProcessor> gp( | |
| 254 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPositi on_GPType, | |
| 255 this->color(), | |
| 256 this->viewMatrix(), | |
| 257 SkMatrix::I(), | |
| 258 false, | |
| 259 this->coverage())); | |
| 260 | |
| 261 size_t vertexStride = gp->getVertexStride(); | |
| 262 SkASSERT(vertexStride == sizeof(SkPoint)); | |
| 263 | |
| 264 batchTarget->initDraw(gp, pipeline); | |
| 265 | |
| 266 // TODO this is hacky, but the only way we have to initialize the GP is to use the | |
| 267 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch | |
| 268 // everywhere we can remove this nastiness | |
| 269 GrPipelineInfo init; | |
| 270 init.fColorIgnored = fBatch.fColorIgnored; | |
| 271 init.fOverrideColor = GrColor_ILLEGAL; | |
| 272 init.fCoverageIgnored = fBatch.fCoverageIgnored; | |
| 273 init.fUsesLocalCoords = this->usesLocalCoords(); | |
| 274 gp->initBatchTracker(batchTarget->currentBatchTracker(), init); | |
| 275 | |
| 276 int instanceCount = fGeoData.count(); | |
| 277 | |
| 278 // compute number of vertices | |
| 279 int maxVertices = 0; | |
| 280 | |
| 281 // We will use index buffers if we have multiple paths or one path with multiple contours | |
| 282 bool isIndexed = instanceCount > 1; | |
| 283 for (int i = 0; i < instanceCount; i++) { | |
| 284 Geometry& args = fGeoData[i]; | |
| 285 | |
| 286 int contourCount; | |
| 287 maxVertices += GrPathUtils::worstCasePointCount(args.fPath, &contour Count, | |
| 288 args.fTolerance); | |
| 289 | |
| 290 isIndexed = isIndexed || contourCount > 1; | |
| 291 } | |
| 292 | |
| 293 // determine primitiveType | |
| 294 int maxIndices = 0; | |
| 295 GrPrimitiveType primitiveType; | |
| 296 if (this->isHairline()) { | |
| 297 if (isIndexed) { | |
| 298 maxIndices = 2 * maxVertices; | |
| 299 primitiveType = kLines_GrPrimitiveType; | |
| 300 } else { | |
| 301 primitiveType = kLineStrip_GrPrimitiveType; | |
| 302 } | |
| 242 } else { | 303 } else { |
| 243 *primType = kLineStrip_GrPrimitiveType; | 304 if (isIndexed) { |
| 244 } | 305 maxIndices = 3 * maxVertices; |
| 245 } else { | 306 primitiveType = kTriangles_GrPrimitiveType; |
| 246 if (indexed) { | 307 } else { |
| 247 maxIdxs = 3 * maxPts; | 308 primitiveType = kTriangleFan_GrPrimitiveType; |
| 248 *primType = kTriangles_GrPrimitiveType; | 309 } |
| 310 } | |
| 311 | |
| 312 // allocate vertex / index buffers | |
| 313 const GrVertexBuffer* vertexBuffer; | |
| 314 int firstVertex; | |
| 315 | |
| 316 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, | |
| 317 maxVertices, | |
| 318 &vertexBuffer, | |
| 319 &firstVertex); | |
| 320 | |
| 321 const GrIndexBuffer* indexBuffer; | |
| 322 int firstIndex; | |
| 323 | |
| 324 void* indices = NULL; | |
| 325 if (isIndexed) { | |
| 326 indices = batchTarget->indexPool()->makeSpace(maxIndices, | |
| 327 &indexBuffer, | |
| 328 &firstIndex); | |
| 329 } | |
| 330 | |
| 331 // fill buffers | |
| 332 int vertexOffset = 0; | |
| 333 int indexOffset = 0; | |
| 334 for (int i = 0; i < instanceCount; i++) { | |
| 335 Geometry& args = fGeoData[i]; | |
| 336 | |
| 337 int vertexCnt = 0; | |
| 338 int indexCnt = 0; | |
| 339 if (!this->createGeom(vertices, | |
| 340 vertexOffset, | |
| 341 indices, | |
| 342 indexOffset, | |
| 343 &vertexCnt, | |
| 344 &indexCnt, | |
| 345 args.fPath, | |
| 346 args.fTolerance, | |
| 347 isIndexed)) { | |
| 348 return; | |
| 349 } | |
| 350 | |
| 351 vertexOffset += vertexCnt; | |
| 352 indexOffset += indexCnt; | |
| 353 } | |
| 354 SkASSERT(vertexOffset <= maxVertices && indexOffset <= maxIndices); | |
| 355 | |
| 356 GrDrawTarget::DrawInfo drawInfo; | |
| 357 drawInfo.setPrimitiveType(primitiveType); | |
| 358 drawInfo.setVertexBuffer(vertexBuffer); | |
| 359 drawInfo.setStartVertex(firstVertex); | |
| 360 drawInfo.setVertexCount(vertexOffset); | |
| 361 if (isIndexed) { | |
| 362 drawInfo.setIndexBuffer(indexBuffer); | |
| 363 drawInfo.setStartIndex(firstIndex); | |
| 364 drawInfo.setIndexCount(indexOffset); | |
| 249 } else { | 365 } else { |
| 250 *primType = kTriangleFan_GrPrimitiveType; | 366 drawInfo.setStartIndex(0); |
| 251 } | 367 drawInfo.setIndexCount(0); |
| 252 } | 368 } |
| 253 | 369 batchTarget->draw(drawInfo); |
| 254 if (!arg->set(target, maxPts, GrDefaultGeoProcFactory::DefaultVertexStride() , maxIdxs)) { | 370 } |
| 255 return false; | 371 |
| 256 } | 372 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
| 257 SkASSERT(GrDefaultGeoProcFactory::DefaultVertexStride() == sizeof(SkPoint)); | 373 |
| 258 | 374 private: |
| 259 uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices()); | 375 DefaultPathBatch(const Geometry& geometry, uint8_t coverage, const SkMatrix& viewMatrix, |
| 260 uint16_t* idx = idxBase; | 376 bool isHairline) { |
| 261 uint16_t subpathIdxStart = 0; | 377 this->initClassID<DefaultPathBatch>(); |
| 262 | 378 fBatch.fCoverage = coverage; |
| 263 SkPoint* base = reinterpret_cast<SkPoint*>(arg->vertices()); | 379 fBatch.fIsHairline = isHairline; |
| 264 SkASSERT(base); | 380 fBatch.fViewMatrix = viewMatrix; |
| 265 SkPoint* vert = base; | 381 fGeoData.push_back(geometry); |
| 266 | 382 } |
| 267 SkPoint pts[4]; | 383 |
| 268 | 384 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { |
| 269 bool first = true; | 385 DefaultPathBatch* that = t->cast<DefaultPathBatch>(); |
| 270 int subpath = 0; | 386 |
| 271 | 387 if (this->color() != that->color()) { |
| 272 SkPath::Iter iter(path, false); | 388 return false; |
| 273 | 389 } |
| 274 for (;;) { | 390 |
| 275 SkPath::Verb verb = iter.next(pts); | 391 if (this->coverage() != that->coverage()) { |
| 276 switch (verb) { | 392 return false; |
| 277 case SkPath::kMove_Verb: | 393 } |
| 278 if (!first) { | 394 |
| 279 uint16_t currIdx = (uint16_t) (vert - base); | 395 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { |
| 280 subpathIdxStart = currIdx; | 396 return false; |
| 281 ++subpath; | 397 } |
| 398 | |
| 399 if (this->isHairline() != that->isHairline()) { | |
| 400 return false; | |
| 401 } | |
| 402 | |
| 403 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; | |
| 404 return true; | |
| 405 } | |
| 406 | |
| 407 bool createGeom(void* vertices, | |
| 408 size_t vertexOffset, | |
| 409 void* indices, | |
| 410 size_t indexOffset, | |
| 411 int* vertexCnt, | |
| 412 int* indexCnt, | |
| 413 const SkPath& path, | |
| 414 SkScalar srcSpaceTol, | |
| 415 bool isIndexed) { | |
| 416 { | |
| 417 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol); | |
| 418 | |
| 419 uint16_t* idxBase = reinterpret_cast<uint16_t*>(indices) + indexOffs et; | |
| 420 uint16_t* idx = idxBase; | |
| 421 uint16_t subpathIdxStart = vertexOffset; | |
| 422 | |
| 423 SkPoint* base = reinterpret_cast<SkPoint*>(vertices) + vertexOffset; | |
| 424 SkPoint* vert = base; | |
| 425 | |
| 426 SkPoint pts[4]; | |
| 427 | |
| 428 bool first = true; | |
| 429 int subpath = 0; | |
| 430 | |
| 431 SkPath::Iter iter(path, false); | |
| 432 | |
| 433 bool done = false; | |
| 434 while (!done) { | |
| 435 SkPath::Verb verb = iter.next(pts); | |
| 436 switch (verb) { | |
| 437 case SkPath::kMove_Verb: | |
| 438 if (!first) { | |
| 439 uint16_t currIdx = (uint16_t) (vert - base) + vertex Offset; | |
| 440 subpathIdxStart = currIdx; | |
| 441 ++subpath; | |
| 442 } | |
| 443 *vert = pts[0]; | |
| 444 vert++; | |
| 445 break; | |
| 446 case SkPath::kLine_Verb: | |
| 447 if (isIndexed) { | |
| 448 uint16_t prevIdx = (uint16_t)(vert - base) - 1 + ver texOffset; | |
| 449 append_countour_edge_indices(this->isHairline(), sub pathIdxStart, | |
| 450 prevIdx, &idx); | |
| 451 } | |
| 452 *(vert++) = pts[1]; | |
| 453 break; | |
| 454 case SkPath::kConic_Verb: { | |
| 455 SkScalar weight = iter.conicWeight(); | |
| 456 SkAutoConicToQuads converter; | |
| 457 // Converting in src-space, hance the finer tolerance (0 .25) | |
| 458 // TODO: find a way to do this in dev-space so the toler ance means something | |
| 459 const SkPoint* quadPts = converter.computeQuads(pts, wei ght, 0.25f); | |
| 460 for (int i = 0; i < converter.countQuads(); ++i) { | |
| 461 add_quad(&vert, base, quadPts + i*2, srcSpaceTolSqd, srcSpaceTol, | |
| 462 isIndexed, this->isHairline(), subpathIdxSt art, vertexOffset, &idx); | |
|
egdaniel
2015/02/18 15:16:57
100 chars
| |
| 463 } | |
| 464 break; | |
| 465 } | |
| 466 case SkPath::kQuad_Verb: | |
| 467 add_quad(&vert, base, pts, srcSpaceTolSqd, srcSpaceTol, isIndexed, | |
| 468 this->isHairline(), subpathIdxStart, vertexOffs et, &idx); | |
| 469 break; | |
| 470 case SkPath::kCubic_Verb: { | |
| 471 // first pt of cubic is the pt we ended on in previous s tep | |
| 472 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1 + ver texOffset; | |
| 473 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicP oints( | |
| 474 pts[0], pts[1], pts[2], pts[3], | |
| 475 srcSpaceTolSqd, &vert, | |
| 476 GrPathUtils::cubicPointCount(pts, srcSpa ceTol)); | |
| 477 if (isIndexed) { | |
| 478 for (uint16_t i = 0; i < numPts; ++i) { | |
| 479 append_countour_edge_indices(this->isHairline(), subpathIdxStart, | |
| 480 firstCPtIdx + i, &i dx); | |
| 481 } | |
| 482 } | |
| 483 break; | |
| 484 } | |
| 485 case SkPath::kClose_Verb: | |
| 486 break; | |
| 487 case SkPath::kDone_Verb: | |
| 488 // uint16_t currIdx = (uint16_t) (vert - base); | |
|
egdaniel
2015/02/18 15:16:57
is the commented line needed for any reason
| |
| 489 done = true; | |
| 282 } | 490 } |
| 283 *vert = pts[0]; | 491 first = false; |
| 284 vert++; | |
| 285 break; | |
| 286 case SkPath::kLine_Verb: | |
| 287 if (indexed) { | |
| 288 uint16_t prevIdx = (uint16_t)(vert - base) - 1; | |
| 289 append_countour_edge_indices(isHairline, subpathIdxStart, | |
| 290 prevIdx, &idx); | |
| 291 } | |
| 292 *(vert++) = pts[1]; | |
| 293 break; | |
| 294 case SkPath::kConic_Verb: { | |
| 295 SkScalar weight = iter.conicWeight(); | |
| 296 SkAutoConicToQuads converter; | |
| 297 // Converting in src-space, hance the finer tolerance (0.25) | |
| 298 // TODO: find a way to do this in dev-space so the tolerance mea ns something | |
| 299 const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.2 5f); | |
| 300 for (int i = 0; i < converter.countQuads(); ++i) { | |
| 301 add_quad(&vert, base, quadPts + i*2, srcSpaceTolSqd, srcSpac eTol, indexed, | |
| 302 isHairline, subpathIdxStart, &idx); | |
| 303 } | |
| 304 break; | |
| 305 } | 492 } |
| 306 case SkPath::kQuad_Verb: | 493 |
|
egdaniel
2015/02/18 15:16:57
was there a reason to remove the asserts in that w
joshualitt
2015/02/20 14:31:46
I put an assert at the end of the whole thing(line
| |
| 307 add_quad(&vert, base, pts, srcSpaceTolSqd, srcSpaceTol, indexed, | 494 *vertexCnt = static_cast<int>(vert - base); |
| 308 isHairline, subpathIdxStart, &idx); | 495 *indexCnt = static_cast<int>(idx - idxBase); |
| 309 break; | 496 |
| 310 case SkPath::kCubic_Verb: { | 497 } |
| 311 // first pt of cubic is the pt we ended on in previous step | 498 return true; |
| 312 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1; | 499 } |
| 313 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints( | 500 |
| 314 pts[0], pts[1], pts[2], pts[3], | 501 GrColor color() const { return fBatch.fColor; } |
| 315 srcSpaceTolSqd, &vert, | 502 uint8_t coverage() const { return fBatch.fCoverage; } |
| 316 GrPathUtils::cubicPointCount(pts, srcSpaceTol)); | 503 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
| 317 if (indexed) { | 504 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } |
| 318 for (uint16_t i = 0; i < numPts; ++i) { | 505 bool isHairline() const { return fBatch.fIsHairline; } |
| 319 append_countour_edge_indices(isHairline, subpathIdxStart , | 506 |
| 320 firstCPtIdx + i, &idx); | 507 struct BatchTracker { |
| 321 } | 508 GrColor fColor; |
| 322 } | 509 uint8_t fCoverage; |
| 323 break; | 510 SkMatrix fViewMatrix; |
| 324 } | 511 bool fUsesLocalCoords; |
| 325 case SkPath::kClose_Verb: | 512 bool fColorIgnored; |
| 326 break; | 513 bool fCoverageIgnored; |
| 327 case SkPath::kDone_Verb: | 514 bool fIsHairline; |
| 328 // uint16_t currIdx = (uint16_t) (vert - base); | 515 }; |
| 329 goto FINISHED; | 516 |
| 330 } | 517 BatchTracker fBatch; |
| 331 first = false; | 518 SkSTArray<1, Geometry, true> fGeoData; |
| 332 } | 519 }; |
| 333 FINISHED: | |
| 334 SkASSERT((vert - base) <= maxPts); | |
| 335 SkASSERT((idx - idxBase) <= maxIdxs); | |
| 336 | |
| 337 *vertexCnt = static_cast<int>(vert - base); | |
| 338 *indexCnt = static_cast<int>(idx - idxBase); | |
| 339 | |
| 340 } | |
| 341 return true; | |
| 342 } | |
| 343 | 520 |
| 344 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, | 521 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, |
| 345 GrPipelineBuilder* pipelineBuilder, | 522 GrPipelineBuilder* pipelineBuilder, |
| 346 GrColor color, | 523 GrColor color, |
| 347 const SkMatrix& viewMatrix, | 524 const SkMatrix& viewMatrix, |
| 348 const SkPath& path, | 525 const SkPath& path, |
| 349 const SkStrokeRec& origStroke, | 526 const SkStrokeRec& origStroke, |
| 350 bool stencilOnly) { | 527 bool stencilOnly) { |
| 351 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); | 528 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); |
| 352 | 529 |
| 353 SkScalar hairlineCoverage; | 530 SkScalar hairlineCoverage; |
| 354 uint8_t newCoverage = 0xff; | 531 uint8_t newCoverage = 0xff; |
| 355 if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { | 532 if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { |
| 356 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); | 533 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); |
| 357 | 534 |
| 358 if (!stroke->isHairlineStyle()) { | 535 if (!stroke->isHairlineStyle()) { |
| 359 stroke.writable()->setHairlineStyle(); | 536 stroke.writable()->setHairlineStyle(); |
| 360 } | 537 } |
| 361 } | 538 } |
| 362 | 539 |
| 363 SkScalar tol = SK_Scalar1; | 540 const bool isHairline = stroke->isHairlineStyle(); |
| 364 tol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, path.getBounds()); | |
| 365 | 541 |
| 366 int vertexCnt; | |
| 367 int indexCnt; | |
| 368 GrPrimitiveType primType; | |
| 369 GrDrawTarget::AutoReleaseGeometry arg; | |
| 370 if (!this->createGeom(target, | |
| 371 pipelineBuilder, | |
| 372 &primType, | |
| 373 &vertexCnt, | |
| 374 &indexCnt, | |
| 375 &arg, | |
| 376 path, | |
| 377 *stroke, | |
| 378 tol)) { | |
| 379 return false; | |
| 380 } | |
| 381 // Save the current xp on the draw state so we can reset it if needed | 542 // Save the current xp on the draw state so we can reset it if needed |
| 382 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXP Factory())); | 543 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXP Factory())); |
| 383 // face culling doesn't make sense here | 544 // face culling doesn't make sense here |
| 384 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace() ); | 545 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace() ); |
| 385 | 546 |
| 386 int passCount = 0; | 547 int passCount = 0; |
| 387 const GrStencilSettings* passes[3]; | 548 const GrStencilSettings* passes[3]; |
| 388 GrPipelineBuilder::DrawFace drawFace[3]; | 549 GrPipelineBuilder::DrawFace drawFace[3]; |
| 389 bool reverse = false; | 550 bool reverse = false; |
| 390 bool lastPassIsBounds; | 551 bool lastPassIsBounds; |
| 391 | 552 |
| 392 if (stroke->isHairlineStyle()) { | 553 if (isHairline) { |
| 393 passCount = 1; | 554 passCount = 1; |
| 394 if (stencilOnly) { | 555 if (stencilOnly) { |
| 395 passes[0] = &gDirectToStencil; | 556 passes[0] = &gDirectToStencil; |
| 396 } else { | 557 } else { |
| 397 passes[0] = NULL; | 558 passes[0] = NULL; |
| 398 } | 559 } |
| 399 lastPassIsBounds = false; | 560 lastPassIsBounds = false; |
| 400 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; | 561 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; |
| 401 } else { | 562 } else { |
| 402 if (single_pass_path(path, *stroke)) { | 563 if (single_pass_path(path, *stroke)) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 } | 629 } |
| 469 } | 630 } |
| 470 break; | 631 break; |
| 471 default: | 632 default: |
| 472 SkDEBUGFAIL("Unknown path fFill!"); | 633 SkDEBUGFAIL("Unknown path fFill!"); |
| 473 return false; | 634 return false; |
| 474 } | 635 } |
| 475 } | 636 } |
| 476 } | 637 } |
| 477 | 638 |
| 639 SkScalar tol = SK_Scalar1; | |
| 640 SkScalar srcSpaceTol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, pat h.getBounds()); | |
| 641 | |
| 478 SkRect devBounds; | 642 SkRect devBounds; |
| 479 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB ounds); | 643 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB ounds); |
| 480 | 644 |
| 481 for (int p = 0; p < passCount; ++p) { | 645 for (int p = 0; p < passCount; ++p) { |
| 482 pipelineBuilder->setDrawFace(drawFace[p]); | 646 pipelineBuilder->setDrawFace(drawFace[p]); |
| 483 if (passes[p]) { | 647 if (passes[p]) { |
| 484 *pipelineBuilder->stencil() = *passes[p]; | 648 *pipelineBuilder->stencil() = *passes[p]; |
| 485 } | 649 } |
| 486 | 650 |
| 487 if (lastPassIsBounds && (p == passCount-1)) { | 651 if (lastPassIsBounds && (p == passCount-1)) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 506 bounds = path.getBounds(); | 670 bounds = path.getBounds(); |
| 507 } | 671 } |
| 508 GrDrawTarget::AutoGeometryPush agp(target); | 672 GrDrawTarget::AutoGeometryPush agp(target); |
| 509 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S kMatrix::I() : | 673 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S kMatrix::I() : |
| 510 v iewMatrix; | 674 v iewMatrix; |
| 511 target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &local Matrix); | 675 target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &local Matrix); |
| 512 } else { | 676 } else { |
| 513 if (passCount > 1) { | 677 if (passCount > 1) { |
| 514 pipelineBuilder->setDisableColorXPFactory(); | 678 pipelineBuilder->setDisableColorXPFactory(); |
| 515 } | 679 } |
| 516 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); | 680 |
| 517 SkAutoTUnref<const GrGeometryProcessor> gp( | 681 DefaultPathBatch::Geometry geometry; |
| 518 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPo sition_GPType, | 682 geometry.fColor = color; |
| 519 color, | 683 geometry.fPath = path; |
| 520 viewMatrix, | 684 geometry.fTolerance = srcSpaceTol; |
| 521 SkMatrix::I(), | 685 SkDEBUGCODE(geometry.fDevBounds = devBounds;) |
| 522 false, | 686 |
| 523 newCoverage)); | 687 SkAutoTUnref<GrBatch> batch(DefaultPathBatch::Create(geometry, newCo verage, viewMatrix, |
| 524 if (indexCnt) { | 688 isHairline)); |
| 525 target->drawIndexed(pipelineBuilder, | 689 |
| 526 gp, | 690 target->drawBatch(pipelineBuilder, batch, &devBounds); |
| 527 primType, | |
| 528 0, | |
| 529 0, | |
| 530 vertexCnt, | |
| 531 indexCnt, | |
| 532 &devBounds); | |
| 533 } else { | |
| 534 target->drawNonIndexed(pipelineBuilder, gp, primType, 0, vertexC nt, &devBounds); | |
| 535 } | |
| 536 } | 691 } |
| 537 } | 692 } |
| 538 return true; | 693 return true; |
| 539 } | 694 } |
| 540 | 695 |
| 541 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, | 696 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, |
| 542 const GrPipelineBuilder* pipelineBuilder , | 697 const GrPipelineBuilder* pipelineBuilder , |
| 543 const SkMatrix& viewMatrix, | 698 const SkMatrix& viewMatrix, |
| 544 const SkPath& path, | 699 const SkPath& path, |
| 545 const SkStrokeRec& stroke, | 700 const SkStrokeRec& stroke, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 568 | 723 |
| 569 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, | 724 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, |
| 570 GrPipelineBuilder* pipelineBuilder, | 725 GrPipelineBuilder* pipelineBuilder, |
| 571 const SkMatrix& viewMatrix, | 726 const SkMatrix& viewMatrix, |
| 572 const SkPath& path, | 727 const SkPath& path, |
| 573 const SkStrokeRec& stroke) { | 728 const SkStrokeRec& stroke) { |
| 574 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); | 729 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); |
| 575 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); | 730 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); |
| 576 this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, p ath, stroke, true); | 731 this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, p ath, stroke, true); |
| 577 } | 732 } |
| OLD | NEW |