Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Unified Diff: src/gpu/batches/GrAADistanceFieldPathRenderer.cpp

Issue 1460873002: Add stroking support to distance field path renderer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix Valgrind issue Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/batches/GrAADistanceFieldPathRenderer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/batches/GrAADistanceFieldPathRenderer.cpp
diff --git a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp
index ee5fdb8a804f23fc88d88e4c96e8d02542fdb866..bb388d7af9ae8f8c89df87d14654fd619ecc362a 100644
--- a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp
+++ b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp
@@ -38,7 +38,7 @@ static int g_NumFreedPaths = 0;
// mip levels
static const int kSmallMIP = 32;
-static const int kMediumMIP = 72;
+static const int kMediumMIP = 73;
static const int kLargeMIP = 162;
// Callback to clear out internal path cache when eviction occurs
@@ -84,10 +84,9 @@ GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() {
bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
// TODO: Support inverse fill
- // TODO: Support strokes
if (!args.fShaderCaps->shaderDerivativeSupport() || !args.fAntiAlias ||
- args.fPath->isInverseFillType() || args.fPath->isVolatile() ||
- !args.fStroke->isFillStyle()) {
+ SkStrokeRec::kHairline_Style == args.fStroke->getStyle() ||
+ args.fPath->isInverseFillType() || args.fPath->isVolatile()) {
return false;
}
@@ -96,12 +95,22 @@ bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c
return false;
}
- // only support paths smaller than 64x64, scaled to less than 256x256
+ // only support paths with bounds within kMediumMIP by kMediumMIP,
+ // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP
// 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());
- return maxDim < 64.f && maxDim * maxScale < 256.f;
+ // 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;
}
////////////////////////////////////////////////////////////////////////////////
@@ -118,8 +127,20 @@ public:
typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList;
struct Geometry {
- Geometry(const SkStrokeRec& stroke) : fStroke(stroke) {}
+ 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);
+ }
+ }
+ }
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;
@@ -225,8 +246,7 @@ private:
}
// check to see if path is cached
- // TODO: handle stroked vs. filled version of same path
- PathData::Key key = { args.fPath.getGenerationID(), desiredDimension };
+ PathData::Key key(args.fGenID, desiredDimension, args.fStroke);
args.fPathData = fPathCache->find(key);
if (nullptr == args.fPathData || !atlas->hasID(args.fPathData->fID)) {
// Remove the stale cache entry
@@ -244,6 +264,7 @@ private:
atlas,
args.fPathData,
args.fPath,
+ args.fGenID,
args.fStroke,
args.fAntiAlias,
desiredDimension,
@@ -301,8 +322,9 @@ private:
GrBatchAtlas* atlas,
PathData* pathData,
const SkPath& path,
- const SkStrokeRec&
- stroke, bool antiAlias,
+ uint32_t genID,
+ const SkStrokeRec& stroke,
+ bool antiAlias,
uint32_t dimension,
SkScalar scale) {
const SkRect& bounds = path.getBounds();
@@ -333,41 +355,25 @@ private:
drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad);
// setup bitmap backing
- // 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());
-
+ SkASSERT(devPathBounds.fLeft == 0);
+ SkASSERT(devPathBounds.fTop == 0);
SkAutoPixmapStorage dst;
- if (!dst.tryAlloc(SkImageInfo::MakeA8(pathBounds.width(),
- pathBounds.height()))) {
+ if (!dst.tryAlloc(SkImageInfo::MakeA8(devPathBounds.width(),
+ devPathBounds.height()))) {
return false;
}
sk_bzero(dst.writable_addr(), dst.getSafeSize());
// rasterize path
SkPaint paint;
- 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.setStyle(SkPaint::kFill_Style);
paint.setAntiAlias(antiAlias);
SkDraw draw;
sk_bzero(&draw, sizeof(draw));
SkRasterClip rasterClip;
- rasterClip.setRect(pathBounds);
+ rasterClip.setRect(devPathBounds);
draw.fRC = &rasterClip;
draw.fClip = &rasterClip.bwRgn();
draw.fMatrix = &drawMatrix;
@@ -403,8 +409,7 @@ private:
}
// add to cache
- pathData->fKey.fGenID = path.getGenerationID();
- pathData->fKey.fDimension = dimension;
+ pathData->fKey = PathData::Key(genID, dimension, stroke);
pathData->fScale = scale;
pathData->fID = id;
// change the scaled rect to match the size of the inset distance field
@@ -543,9 +548,17 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(const DrawPathArgs& args) {
}
AADistanceFieldPathBatch::Geometry geometry(*args.fStroke);
- geometry.fPath = *args.fPath;
+ if (SkStrokeRec::kFill_Style == args.fStroke->getStyle()) {
+ geometry.fPath = *args.fPath;
+ } else {
+ args.fStroke->applyToPath(&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));
@@ -620,6 +633,7 @@ DRAW_BATCH_TEST_DEFINE(AADistanceFieldPathBatch) {
AADistanceFieldPathBatch::Geometry geometry(GrTest::TestStrokeRec(random));
geometry.fPath = GrTest::TestPath(random);
geometry.fAntiAlias = random->nextBool();
+ geometry.fGenID = random->nextU();
return AADistanceFieldPathBatch::Create(geometry, color, viewMatrix,
gTestStruct.fAtlas,
« no previous file with comments | « src/gpu/batches/GrAADistanceFieldPathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698