Index: src/gpu/batches/GrAADistanceFieldPathRenderer.cpp |
diff --git a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp |
index 4eff0c40797d759e4898c2b52503af6b065c16f2..ee5fdb8a804f23fc88d88e4c96e8d02542fdb866 100644 |
--- a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp |
+++ b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp |
@@ -38,7 +38,7 @@ |
// mip levels |
static const int kSmallMIP = 32; |
-static const int kMediumMIP = 73; |
+static const int kMediumMIP = 72; |
static const int kLargeMIP = 162; |
// Callback to clear out internal path cache when eviction occurs |
@@ -84,9 +84,10 @@ |
bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { |
// TODO: Support inverse fill |
+ // TODO: Support strokes |
if (!args.fShaderCaps->shaderDerivativeSupport() || !args.fAntiAlias || |
- SkStrokeRec::kHairline_Style == args.fStroke->getStyle() || |
- args.fPath->isInverseFillType() || args.fPath->isVolatile()) { |
+ args.fPath->isInverseFillType() || args.fPath->isVolatile() || |
+ !args.fStroke->isFillStyle()) { |
return false; |
} |
@@ -95,22 +96,12 @@ |
return false; |
} |
- // only support paths with bounds within kMediumMIP by kMediumMIP, |
- // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP |
+ // only support paths smaller than 64x64, scaled to less than 256x256 |
// the goal is to accelerate rendering of lots of small paths that may be scaling |
SkScalar maxScale = args.fViewMatrix->getMaxScale(); |
const SkRect& bounds = args.fPath->getBounds(); |
SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); |
- // Approximate stroked size by adding the maximum of the stroke width or 2x the miter limit |
- if (!args.fStroke->isFillStyle()) { |
- SkScalar extraWidth = args.fStroke->getWidth(); |
- if (SkPaint::kMiter_Join == args.fStroke->getJoin()) { |
- extraWidth = SkTMax(extraWidth, 2.0f*args.fStroke->getMiter()); |
- } |
- maxDim += extraWidth; |
- } |
- |
- return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP; |
+ return maxDim < 64.f && maxDim * maxScale < 256.f; |
} |
//////////////////////////////////////////////////////////////////////////////// |
@@ -127,20 +118,8 @@ |
typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList; |
struct Geometry { |
- Geometry(const SkStrokeRec& stroke) : fStroke(stroke) { |
- if (!stroke.needToApply()) { |
- // purify unused values to ensure binary equality |
- fStroke.setStrokeParams(SkPaint::kDefault_Cap, SkPaint::kDefault_Join, |
- SkIntToScalar(4)); |
- if (fStroke.getWidth() < 0) { |
- fStroke.setStrokeStyle(-1.0f); |
- } |
- } |
- } |
+ Geometry(const SkStrokeRec& stroke) : fStroke(stroke) {} |
SkPath fPath; |
- // The unique ID of the path involved in this draw. This may be different than the ID |
- // in fPath since that path may have resulted from a SkStrokeRec::applyToPath call. |
- uint32_t fGenID; |
SkStrokeRec fStroke; |
bool fAntiAlias; |
PathData* fPathData; |
@@ -246,7 +225,8 @@ |
} |
// check to see if path is cached |
- PathData::Key key(args.fGenID, desiredDimension, args.fStroke); |
+ // TODO: handle stroked vs. filled version of same path |
+ PathData::Key key = { args.fPath.getGenerationID(), desiredDimension }; |
args.fPathData = fPathCache->find(key); |
if (nullptr == args.fPathData || !atlas->hasID(args.fPathData->fID)) { |
// Remove the stale cache entry |
@@ -264,7 +244,6 @@ |
atlas, |
args.fPathData, |
args.fPath, |
- args.fGenID, |
args.fStroke, |
args.fAntiAlias, |
desiredDimension, |
@@ -322,9 +301,8 @@ |
GrBatchAtlas* atlas, |
PathData* pathData, |
const SkPath& path, |
- uint32_t genID, |
- const SkStrokeRec& stroke, |
- bool antiAlias, |
+ const SkStrokeRec& |
+ stroke, bool antiAlias, |
uint32_t dimension, |
SkScalar scale) { |
const SkRect& bounds = path.getBounds(); |
@@ -355,25 +333,41 @@ |
drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad); |
// setup bitmap backing |
- SkASSERT(devPathBounds.fLeft == 0); |
- SkASSERT(devPathBounds.fTop == 0); |
+ // Now translate so the bound's UL corner is at the origin |
+ drawMatrix.postTranslate(-devPathBounds.fLeft * SK_Scalar1, |
+ -devPathBounds.fTop * SK_Scalar1); |
+ SkIRect pathBounds = SkIRect::MakeWH(devPathBounds.width(), |
+ devPathBounds.height()); |
+ |
SkAutoPixmapStorage dst; |
- if (!dst.tryAlloc(SkImageInfo::MakeA8(devPathBounds.width(), |
- devPathBounds.height()))) { |
+ if (!dst.tryAlloc(SkImageInfo::MakeA8(pathBounds.width(), |
+ pathBounds.height()))) { |
return false; |
} |
sk_bzero(dst.writable_addr(), dst.getSafeSize()); |
// rasterize path |
SkPaint paint; |
- paint.setStyle(SkPaint::kFill_Style); |
+ if (stroke.isHairlineStyle()) { |
+ paint.setStyle(SkPaint::kStroke_Style); |
+ paint.setStrokeWidth(SK_Scalar1); |
+ } else { |
+ if (stroke.isFillStyle()) { |
+ paint.setStyle(SkPaint::kFill_Style); |
+ } else { |
+ paint.setStyle(SkPaint::kStroke_Style); |
+ paint.setStrokeJoin(stroke.getJoin()); |
+ paint.setStrokeCap(stroke.getCap()); |
+ paint.setStrokeWidth(stroke.getWidth()); |
+ } |
+ } |
paint.setAntiAlias(antiAlias); |
SkDraw draw; |
sk_bzero(&draw, sizeof(draw)); |
SkRasterClip rasterClip; |
- rasterClip.setRect(devPathBounds); |
+ rasterClip.setRect(pathBounds); |
draw.fRC = &rasterClip; |
draw.fClip = &rasterClip.bwRgn(); |
draw.fMatrix = &drawMatrix; |
@@ -409,7 +403,8 @@ |
} |
// add to cache |
- pathData->fKey = PathData::Key(genID, dimension, stroke); |
+ pathData->fKey.fGenID = path.getGenerationID(); |
+ pathData->fKey.fDimension = dimension; |
pathData->fScale = scale; |
pathData->fID = id; |
// change the scaled rect to match the size of the inset distance field |
@@ -548,17 +543,9 @@ |
} |
AADistanceFieldPathBatch::Geometry geometry(*args.fStroke); |
- if (SkStrokeRec::kFill_Style == args.fStroke->getStyle()) { |
- geometry.fPath = *args.fPath; |
- } else { |
- args.fStroke->applyToPath(&geometry.fPath, *args.fPath); |
- } |
+ geometry.fPath = *args.fPath; |
geometry.fAntiAlias = args.fAntiAlias; |
- // Note: this is the generation ID of the _original_ path. When a new path is |
- // generated due to stroking it is important that the original path's id is used |
- // for caching. |
- geometry.fGenID = args.fPath->getGenerationID(); |
- |
+ |
SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry, args.fColor, |
*args.fViewMatrix, fAtlas, |
&fPathCache, &fPathList)); |