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 SkASSERT(vertexOffset <= maxVertices && indexOffset <= maxIndices); |
| 354 } |
| 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 indexOffsetU16 = (uint16_t)indexOffset; |
| 420 uint16_t vertexOffsetU16 = (uint16_t)vertexOffset; |
| 421 |
| 422 uint16_t* idxBase = reinterpret_cast<uint16_t*>(indices) + indexOffs
etU16; |
| 423 uint16_t* idx = idxBase; |
| 424 uint16_t subpathIdxStart = vertexOffsetU16; |
| 425 |
| 426 SkPoint* base = reinterpret_cast<SkPoint*>(vertices) + vertexOffset; |
| 427 SkPoint* vert = base; |
| 428 |
| 429 SkPoint pts[4]; |
| 430 |
| 431 bool first = true; |
| 432 int subpath = 0; |
| 433 |
| 434 SkPath::Iter iter(path, false); |
| 435 |
| 436 bool done = false; |
| 437 while (!done) { |
| 438 SkPath::Verb verb = iter.next(pts); |
| 439 switch (verb) { |
| 440 case SkPath::kMove_Verb: |
| 441 if (!first) { |
| 442 uint16_t currIdx = (uint16_t) (vert - base) + vertex
OffsetU16; |
| 443 subpathIdxStart = currIdx; |
| 444 ++subpath; |
| 445 } |
| 446 *vert = pts[0]; |
| 447 vert++; |
| 448 break; |
| 449 case SkPath::kLine_Verb: |
| 450 if (isIndexed) { |
| 451 uint16_t prevIdx = (uint16_t)(vert - base) - 1 + ver
texOffsetU16; |
| 452 append_countour_edge_indices(this->isHairline(), sub
pathIdxStart, |
| 453 prevIdx, &idx); |
| 454 } |
| 455 *(vert++) = pts[1]; |
| 456 break; |
| 457 case SkPath::kConic_Verb: { |
| 458 SkScalar weight = iter.conicWeight(); |
| 459 SkAutoConicToQuads converter; |
| 460 // Converting in src-space, hance the finer tolerance (0
.25) |
| 461 // TODO: find a way to do this in dev-space so the toler
ance means something |
| 462 const SkPoint* quadPts = converter.computeQuads(pts, wei
ght, 0.25f); |
| 463 for (int i = 0; i < converter.countQuads(); ++i) { |
| 464 add_quad(&vert, base, quadPts + i*2, srcSpaceTolSqd,
srcSpaceTol, |
| 465 isIndexed, this->isHairline(), subpathIdxSt
art, |
| 466 (int)vertexOffset, &idx); |
| 467 } |
| 468 break; |
| 469 } |
| 470 case SkPath::kQuad_Verb: |
| 471 add_quad(&vert, base, pts, srcSpaceTolSqd, srcSpaceTol,
isIndexed, |
| 472 this->isHairline(), subpathIdxStart, (int)verte
xOffset, &idx); |
| 473 break; |
| 474 case SkPath::kCubic_Verb: { |
| 475 // first pt of cubic is the pt we ended on in previous s
tep |
| 476 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1 + ver
texOffsetU16; |
| 477 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicP
oints( |
| 478 pts[0], pts[1], pts[2], pts[3], |
| 479 srcSpaceTolSqd, &vert, |
| 480 GrPathUtils::cubicPointCount(pts, srcSpa
ceTol)); |
| 481 if (isIndexed) { |
| 482 for (uint16_t i = 0; i < numPts; ++i) { |
| 483 append_countour_edge_indices(this->isHairline(),
subpathIdxStart, |
| 484 firstCPtIdx + i, &i
dx); |
| 485 } |
| 486 } |
| 487 break; |
| 488 } |
| 489 case SkPath::kClose_Verb: |
| 490 break; |
| 491 case SkPath::kDone_Verb: |
| 492 done = true; |
282 } | 493 } |
283 *vert = pts[0]; | 494 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 } | 495 } |
306 case SkPath::kQuad_Verb: | 496 |
307 add_quad(&vert, base, pts, srcSpaceTolSqd, srcSpaceTol, indexed, | 497 *vertexCnt = static_cast<int>(vert - base); |
308 isHairline, subpathIdxStart, &idx); | 498 *indexCnt = static_cast<int>(idx - idxBase); |
309 break; | 499 |
310 case SkPath::kCubic_Verb: { | 500 } |
311 // first pt of cubic is the pt we ended on in previous step | 501 return true; |
312 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1; | 502 } |
313 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints( | 503 |
314 pts[0], pts[1], pts[2], pts[3], | 504 GrColor color() const { return fBatch.fColor; } |
315 srcSpaceTolSqd, &vert, | 505 uint8_t coverage() const { return fBatch.fCoverage; } |
316 GrPathUtils::cubicPointCount(pts, srcSpaceTol)); | 506 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
317 if (indexed) { | 507 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } |
318 for (uint16_t i = 0; i < numPts; ++i) { | 508 bool isHairline() const { return fBatch.fIsHairline; } |
319 append_countour_edge_indices(isHairline, subpathIdxStart
, | 509 |
320 firstCPtIdx + i, &idx); | 510 struct BatchTracker { |
321 } | 511 GrColor fColor; |
322 } | 512 uint8_t fCoverage; |
323 break; | 513 SkMatrix fViewMatrix; |
324 } | 514 bool fUsesLocalCoords; |
325 case SkPath::kClose_Verb: | 515 bool fColorIgnored; |
326 break; | 516 bool fCoverageIgnored; |
327 case SkPath::kDone_Verb: | 517 bool fIsHairline; |
328 // uint16_t currIdx = (uint16_t) (vert - base); | 518 }; |
329 goto FINISHED; | 519 |
330 } | 520 BatchTracker fBatch; |
331 first = false; | 521 SkSTArray<1, Geometry, true> fGeoData; |
332 } | 522 }; |
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 | 523 |
344 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, | 524 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, |
345 GrPipelineBuilder* pipelineBuilder, | 525 GrPipelineBuilder* pipelineBuilder, |
346 GrColor color, | 526 GrColor color, |
347 const SkMatrix& viewMatrix, | 527 const SkMatrix& viewMatrix, |
348 const SkPath& path, | 528 const SkPath& path, |
349 const SkStrokeRec& origStroke, | 529 const SkStrokeRec& origStroke, |
350 bool stencilOnly) { | 530 bool stencilOnly) { |
351 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); | 531 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); |
352 | 532 |
353 SkScalar hairlineCoverage; | 533 SkScalar hairlineCoverage; |
354 uint8_t newCoverage = 0xff; | 534 uint8_t newCoverage = 0xff; |
355 if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { | 535 if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { |
356 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); | 536 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); |
357 | 537 |
358 if (!stroke->isHairlineStyle()) { | 538 if (!stroke->isHairlineStyle()) { |
359 stroke.writable()->setHairlineStyle(); | 539 stroke.writable()->setHairlineStyle(); |
360 } | 540 } |
361 } | 541 } |
362 | 542 |
363 SkScalar tol = SK_Scalar1; | 543 const bool isHairline = stroke->isHairlineStyle(); |
364 tol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, path.getBounds()); | |
365 | 544 |
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 | 545 // Save the current xp on the draw state so we can reset it if needed |
382 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXP
Factory())); | 546 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXP
Factory())); |
383 // face culling doesn't make sense here | 547 // face culling doesn't make sense here |
384 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace()
); | 548 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace()
); |
385 | 549 |
386 int passCount = 0; | 550 int passCount = 0; |
387 const GrStencilSettings* passes[3]; | 551 const GrStencilSettings* passes[3]; |
388 GrPipelineBuilder::DrawFace drawFace[3]; | 552 GrPipelineBuilder::DrawFace drawFace[3]; |
389 bool reverse = false; | 553 bool reverse = false; |
390 bool lastPassIsBounds; | 554 bool lastPassIsBounds; |
391 | 555 |
392 if (stroke->isHairlineStyle()) { | 556 if (isHairline) { |
393 passCount = 1; | 557 passCount = 1; |
394 if (stencilOnly) { | 558 if (stencilOnly) { |
395 passes[0] = &gDirectToStencil; | 559 passes[0] = &gDirectToStencil; |
396 } else { | 560 } else { |
397 passes[0] = NULL; | 561 passes[0] = NULL; |
398 } | 562 } |
399 lastPassIsBounds = false; | 563 lastPassIsBounds = false; |
400 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; | 564 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; |
401 } else { | 565 } else { |
402 if (single_pass_path(path, *stroke)) { | 566 if (single_pass_path(path, *stroke)) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 } | 632 } |
469 } | 633 } |
470 break; | 634 break; |
471 default: | 635 default: |
472 SkDEBUGFAIL("Unknown path fFill!"); | 636 SkDEBUGFAIL("Unknown path fFill!"); |
473 return false; | 637 return false; |
474 } | 638 } |
475 } | 639 } |
476 } | 640 } |
477 | 641 |
| 642 SkScalar tol = SK_Scalar1; |
| 643 SkScalar srcSpaceTol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, pat
h.getBounds()); |
| 644 |
478 SkRect devBounds; | 645 SkRect devBounds; |
479 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB
ounds); | 646 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB
ounds); |
480 | 647 |
481 for (int p = 0; p < passCount; ++p) { | 648 for (int p = 0; p < passCount; ++p) { |
482 pipelineBuilder->setDrawFace(drawFace[p]); | 649 pipelineBuilder->setDrawFace(drawFace[p]); |
483 if (passes[p]) { | 650 if (passes[p]) { |
484 *pipelineBuilder->stencil() = *passes[p]; | 651 *pipelineBuilder->stencil() = *passes[p]; |
485 } | 652 } |
486 | 653 |
487 if (lastPassIsBounds && (p == passCount-1)) { | 654 if (lastPassIsBounds && (p == passCount-1)) { |
(...skipping 18 matching lines...) Expand all Loading... |
506 bounds = path.getBounds(); | 673 bounds = path.getBounds(); |
507 } | 674 } |
508 GrDrawTarget::AutoGeometryPush agp(target); | 675 GrDrawTarget::AutoGeometryPush agp(target); |
509 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S
kMatrix::I() : | 676 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S
kMatrix::I() : |
510 v
iewMatrix; | 677 v
iewMatrix; |
511 target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &local
Matrix); | 678 target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &local
Matrix); |
512 } else { | 679 } else { |
513 if (passCount > 1) { | 680 if (passCount > 1) { |
514 pipelineBuilder->setDisableColorXPFactory(); | 681 pipelineBuilder->setDisableColorXPFactory(); |
515 } | 682 } |
516 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); | 683 |
517 SkAutoTUnref<const GrGeometryProcessor> gp( | 684 DefaultPathBatch::Geometry geometry; |
518 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPo
sition_GPType, | 685 geometry.fColor = color; |
519 color, | 686 geometry.fPath = path; |
520 viewMatrix, | 687 geometry.fTolerance = srcSpaceTol; |
521 SkMatrix::I(), | 688 SkDEBUGCODE(geometry.fDevBounds = devBounds;) |
522 false, | 689 |
523 newCoverage)); | 690 SkAutoTUnref<GrBatch> batch(DefaultPathBatch::Create(geometry, newCo
verage, viewMatrix, |
524 if (indexCnt) { | 691 isHairline)); |
525 target->drawIndexed(pipelineBuilder, | 692 |
526 gp, | 693 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 } | 694 } |
537 } | 695 } |
538 return true; | 696 return true; |
539 } | 697 } |
540 | 698 |
541 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, | 699 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, |
542 const GrPipelineBuilder* pipelineBuilder
, | 700 const GrPipelineBuilder* pipelineBuilder
, |
543 const SkMatrix& viewMatrix, | 701 const SkMatrix& viewMatrix, |
544 const SkPath& path, | 702 const SkPath& path, |
545 const SkStrokeRec& stroke, | 703 const SkStrokeRec& stroke, |
(...skipping 22 matching lines...) Expand all Loading... |
568 | 726 |
569 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, | 727 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, |
570 GrPipelineBuilder* pipelineBuilder, | 728 GrPipelineBuilder* pipelineBuilder, |
571 const SkMatrix& viewMatrix, | 729 const SkMatrix& viewMatrix, |
572 const SkPath& path, | 730 const SkPath& path, |
573 const SkStrokeRec& stroke) { | 731 const SkStrokeRec& stroke) { |
574 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); | 732 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); |
575 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); | 733 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); |
576 this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, p
ath, stroke, true); | 734 this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, p
ath, stroke, true); |
577 } | 735 } |
OLD | NEW |