OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "GrContext.h" | 9 #include "GrContext.h" |
10 | 10 |
(...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 const GrStrokeInfo& strokeInfo) { | 1336 const GrStrokeInfo& strokeInfo) { |
1337 RETURN_IF_ABANDONED | 1337 RETURN_IF_ABANDONED |
1338 if (path.isEmpty()) { | 1338 if (path.isEmpty()) { |
1339 if (path.isInverseFillType()) { | 1339 if (path.isInverseFillType()) { |
1340 this->drawPaint(rt, clip, paint, viewMatrix); | 1340 this->drawPaint(rt, clip, paint, viewMatrix); |
1341 } | 1341 } |
1342 return; | 1342 return; |
1343 } | 1343 } |
1344 | 1344 |
1345 GrColor color = paint.getColor(); | 1345 GrColor color = paint.getColor(); |
1346 if (strokeInfo.isDashed()) { | |
1347 SkPoint pts[2]; | |
1348 if (path.isLine(pts)) { | |
1349 AutoCheckFlush acf(this); | |
1350 GrPipelineBuilder pipelineBuilder; | |
1351 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, cli
p, &paint, &acf); | |
1352 if (NULL == target) { | |
1353 return; | |
1354 } | |
1355 | |
1356 if (GrDashingEffect::DrawDashLine(fGpu, target, &pipelineBuilder, co
lor, viewMatrix, | |
1357 pts, paint, strokeInfo)) { | |
1358 return; | |
1359 } | |
1360 } | |
1361 | |
1362 // Filter dashed path into new path with the dashing applied | |
1363 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); | |
1364 SkTLazy<SkPath> effectPath; | |
1365 GrStrokeInfo newStrokeInfo(strokeInfo, false); | |
1366 SkStrokeRec* stroke = newStrokeInfo.getStrokeRecPtr(); | |
1367 if (SkDashPath::FilterDashPath(effectPath.init(), path, stroke, NULL, in
fo)) { | |
1368 this->drawPath(rt, clip, paint, viewMatrix, *effectPath.get(), newSt
rokeInfo); | |
1369 return; | |
1370 } | |
1371 | |
1372 this->drawPath(rt, clip, paint, viewMatrix, path, newStrokeInfo); | |
1373 return; | |
1374 } | |
1375 | 1346 |
1376 // Note that internalDrawPath may sw-rasterize the path into a scratch textu
re. | 1347 // Note that internalDrawPath may sw-rasterize the path into a scratch textu
re. |
1377 // Scratch textures can be recycled after they are returned to the texture | 1348 // Scratch textures can be recycled after they are returned to the texture |
1378 // cache. This presents a potential hazard for buffered drawing. However, | 1349 // cache. This presents a potential hazard for buffered drawing. However, |
1379 // the writePixels that uploads to the scratch will perform a flush so we're | 1350 // the writePixels that uploads to the scratch will perform a flush so we're |
1380 // OK. | 1351 // OK. |
1381 AutoCheckFlush acf(this); | 1352 AutoCheckFlush acf(this); |
1382 GrPipelineBuilder pipelineBuilder; | 1353 GrPipelineBuilder pipelineBuilder; |
1383 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain
t, &acf); | 1354 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain
t, &acf); |
1384 if (NULL == target) { | 1355 if (NULL == target) { |
1385 return; | 1356 return; |
1386 } | 1357 } |
1387 | 1358 |
1388 GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isC
onvex()); | 1359 GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isC
onvex()); |
1389 | 1360 |
1390 const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec(); | 1361 if (!strokeInfo.isDashed()) { |
| 1362 const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec(); |
| 1363 bool useCoverageAA = paint.isAntiAlias() && |
| 1364 !pipelineBuilder.getRenderTarget()->isMultisampled(); |
1391 | 1365 |
1392 bool useCoverageAA = paint.isAntiAlias() && | 1366 if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) { |
1393 !pipelineBuilder.getRenderTarget()->isMultisampled(); | 1367 // Concave AA paths are expensive - try to avoid them for special ca
ses |
| 1368 SkRect rects[2]; |
1394 | 1369 |
1395 if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) { | 1370 if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, pat
h, strokeRec, |
1396 // Concave AA paths are expensive - try to avoid them for special cases | 1371 rects)) { |
1397 SkRect rects[2]; | 1372 fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, col
or, viewMatrix, |
| 1373 rects); |
| 1374 return; |
| 1375 } |
| 1376 } |
| 1377 SkRect ovalRect; |
| 1378 bool isOval = path.isOval(&ovalRect); |
1398 | 1379 |
1399 if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, path, s
trokeRec, rects)) { | 1380 if (isOval && !path.isInverseFillType()) { |
1400 fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color,
viewMatrix, rects); | 1381 if (fOvalRenderer->drawOval(target, |
1401 return; | 1382 &pipelineBuilder, |
| 1383 color, |
| 1384 viewMatrix, |
| 1385 paint.isAntiAlias(), |
| 1386 ovalRect, |
| 1387 strokeRec)) { |
| 1388 return; |
| 1389 } |
1402 } | 1390 } |
1403 } | 1391 } |
1404 | 1392 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.is
AntiAlias(), |
1405 SkRect ovalRect; | 1393 path, strokeInfo); |
1406 bool isOval = path.isOval(&ovalRect); | |
1407 | |
1408 if (!isOval || path.isInverseFillType() || | |
1409 !fOvalRenderer->drawOval(target, | |
1410 &pipelineBuilder, | |
1411 color, | |
1412 viewMatrix, | |
1413 paint.isAntiAlias(), | |
1414 ovalRect, | |
1415 strokeRec)) { | |
1416 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, pain
t.isAntiAlias(), | |
1417 path, strokeInfo); | |
1418 } | |
1419 } | 1394 } |
1420 | 1395 |
1421 void GrContext::internalDrawPath(GrDrawTarget* target, | 1396 void GrContext::internalDrawPath(GrDrawTarget* target, |
1422 GrPipelineBuilder* pipelineBuilder, | 1397 GrPipelineBuilder* pipelineBuilder, |
1423 const SkMatrix& viewMatrix, | 1398 const SkMatrix& viewMatrix, |
1424 GrColor color, | 1399 GrColor color, |
1425 bool useAA, | 1400 bool useAA, |
1426 const SkPath& path, | 1401 const SkPath& path, |
1427 const GrStrokeInfo& strokeInfo) { | 1402 const GrStrokeInfo& strokeInfo) { |
1428 RETURN_IF_ABANDONED | 1403 RETURN_IF_ABANDONED |
1429 SkASSERT(!path.isEmpty()); | 1404 SkASSERT(!path.isEmpty()); |
1430 | 1405 |
1431 GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target); | 1406 GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target); |
1432 | 1407 |
1433 | 1408 |
1434 // An Assumption here is that path renderer would use some form of tweaking | 1409 // An Assumption here is that path renderer would use some form of tweaking |
1435 // the src color (either the input alpha or in the frag shader) to implement | 1410 // the src color (either the input alpha or in the frag shader) to implement |
1436 // aa. If we have some future driver-mojo path AA that can do the right | 1411 // aa. If we have some future driver-mojo path AA that can do the right |
1437 // thing WRT to the blend then we'll need some query on the PR. | 1412 // thing WRT to the blend then we'll need some query on the PR. |
1438 bool useCoverageAA = useAA && | 1413 bool useCoverageAA = useAA && |
1439 !pipelineBuilder->getRenderTarget()->isMultisampled(); | 1414 !pipelineBuilder->getRenderTarget()->isMultisampled(); |
1440 | 1415 |
1441 | 1416 |
1442 GrPathRendererChain::DrawType type = | 1417 GrPathRendererChain::DrawType type = |
1443 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType : | 1418 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType : |
1444 GrPathRendererChain::kColor_DrawType; | 1419 GrPathRendererChain::kColor_DrawType; |
1445 | 1420 |
1446 const SkPath* pathPtr = &path; | 1421 const SkPath* pathPtr = &path; |
1447 SkTLazy<SkPath> tmpPath; | 1422 SkTLazy<SkPath> tmpPath; |
1448 SkTCopyOnFirstWrite<SkStrokeRec> stroke(strokeInfo.getStrokeRec()); | 1423 const GrStrokeInfo* strokeInfoPtr = &strokeInfo; |
1449 | 1424 |
1450 // Try a 1st time without stroking the path and without allowing the SW rend
erer | 1425 // Try a 1st time without stroking the path and without allowing the SW rend
erer |
1451 GrPathRenderer* pr = this->getPathRenderer(target, pipelineBuilder, viewMatr
ix, *pathPtr, | 1426 GrPathRenderer* pr = this->getPathRenderer(target, pipelineBuilder, viewMatr
ix, *pathPtr, |
1452 *stroke, false, type); | 1427 *strokeInfoPtr, false, type); |
| 1428 |
| 1429 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false); |
| 1430 if (NULL == pr && strokeInfo.isDashed()) { |
| 1431 // It didn't work above, so try again with dashed stroke converted to a
dashless stroke. |
| 1432 if (strokeInfo.applyDash(tmpPath.init(), &dashlessStrokeInfo, *pathPtr))
{ |
| 1433 pathPtr = tmpPath.get(); |
| 1434 if (pathPtr->isEmpty()) { |
| 1435 return; |
| 1436 } |
| 1437 strokeInfoPtr = &dashlessStrokeInfo; |
| 1438 } |
| 1439 pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr
, *strokeInfoPtr, |
| 1440 false, type); |
| 1441 } |
1453 | 1442 |
1454 if (NULL == pr) { | 1443 if (NULL == pr) { |
1455 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, N
ULL)) { | 1444 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMa
trix, NULL)) { |
1456 // It didn't work the 1st time, so try again with the stroked path | 1445 // It didn't work above, so try again with stroke converted to a fil
l. |
1457 stroke.writable()->setResScale(SkScalarAbs(viewMatrix.getMaxScale())
); | 1446 if (!tmpPath.isValid()) { |
1458 if (stroke->applyToPath(tmpPath.init(), *pathPtr)) { | 1447 tmpPath.init(); |
| 1448 } |
| 1449 SkStrokeRec* strokeRec = dashlessStrokeInfo.getStrokeRecPtr(); |
| 1450 strokeRec->setResScale(SkScalarAbs(viewMatrix.getMaxScale())); |
| 1451 if (strokeRec->applyToPath(tmpPath.get(), *pathPtr)) { |
1459 pathPtr = tmpPath.get(); | 1452 pathPtr = tmpPath.get(); |
1460 stroke.writable()->setFillStyle(); | |
1461 if (pathPtr->isEmpty()) { | 1453 if (pathPtr->isEmpty()) { |
1462 return; | 1454 return; |
1463 } | 1455 } |
| 1456 strokeRec->setFillStyle(); |
| 1457 strokeInfoPtr = &dashlessStrokeInfo; |
1464 } | 1458 } |
1465 } | 1459 } |
1466 | 1460 |
1467 // This time, allow SW renderer | 1461 // This time, allow SW renderer |
1468 pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr
, *stroke, true, | 1462 pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr
, *strokeInfoPtr, |
1469 type); | 1463 true, type); |
1470 } | 1464 } |
1471 | 1465 |
1472 if (NULL == pr) { | 1466 if (NULL == pr) { |
1473 #ifdef SK_DEBUG | 1467 #ifdef SK_DEBUG |
1474 SkDebugf("Unable to find path renderer compatible with path.\n"); | 1468 SkDebugf("Unable to find path renderer compatible with path.\n"); |
1475 #endif | 1469 #endif |
1476 return; | 1470 return; |
1477 } | 1471 } |
1478 | 1472 |
1479 pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *stroke,
useCoverageAA); | 1473 pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeIn
foPtr, useCoverageAA); |
1480 } | 1474 } |
1481 | 1475 |
1482 //////////////////////////////////////////////////////////////////////////////// | 1476 //////////////////////////////////////////////////////////////////////////////// |
1483 | 1477 |
1484 void GrContext::flush(int flagsBitfield) { | 1478 void GrContext::flush(int flagsBitfield) { |
1485 if (NULL == fDrawBuffer) { | 1479 if (NULL == fDrawBuffer) { |
1486 return; | 1480 return; |
1487 } | 1481 } |
1488 | 1482 |
1489 if (kDiscard_FlushBit & flagsBitfield) { | 1483 if (kDiscard_FlushBit & flagsBitfield) { |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1866 /* | 1860 /* |
1867 * This method finds a path renderer that can draw the specified path on | 1861 * This method finds a path renderer that can draw the specified path on |
1868 * the provided target. | 1862 * the provided target. |
1869 * Due to its expense, the software path renderer has split out so it can | 1863 * Due to its expense, the software path renderer has split out so it can |
1870 * can be individually allowed/disallowed via the "allowSW" boolean. | 1864 * can be individually allowed/disallowed via the "allowSW" boolean. |
1871 */ | 1865 */ |
1872 GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, | 1866 GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, |
1873 const GrPipelineBuilder* pipelineBuil
der, | 1867 const GrPipelineBuilder* pipelineBuil
der, |
1874 const SkMatrix& viewMatrix, | 1868 const SkMatrix& viewMatrix, |
1875 const SkPath& path, | 1869 const SkPath& path, |
1876 const SkStrokeRec& stroke, | 1870 const GrStrokeInfo& stroke, |
1877 bool allowSW, | 1871 bool allowSW, |
1878 GrPathRendererChain::DrawType drawTyp
e, | 1872 GrPathRendererChain::DrawType drawTyp
e, |
1879 GrPathRendererChain::StencilSupport*
stencilSupport) { | 1873 GrPathRendererChain::StencilSupport*
stencilSupport) { |
1880 | 1874 |
1881 if (NULL == fPathRendererChain) { | 1875 if (NULL == fPathRendererChain) { |
1882 fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this)); | 1876 fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this)); |
1883 } | 1877 } |
1884 | 1878 |
1885 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target, | 1879 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target, |
1886 pipelineBuilder, | 1880 pipelineBuilder, |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2031 } | 2025 } |
2032 } | 2026 } |
2033 | 2027 |
2034 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { | 2028 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { |
2035 fGpu->removeGpuTraceMarker(marker); | 2029 fGpu->removeGpuTraceMarker(marker); |
2036 if (fDrawBuffer) { | 2030 if (fDrawBuffer) { |
2037 fDrawBuffer->removeGpuTraceMarker(marker); | 2031 fDrawBuffer->removeGpuTraceMarker(marker); |
2038 } | 2032 } |
2039 } | 2033 } |
2040 | 2034 |
OLD | NEW |