From 7704754049cac4794f27496efa90acea963b8881 Mon Sep 17 00:00:00 2001 From: Jim Van Verth Date: Wed, 11 Jan 2017 14:17:00 -0500 Subject: [PATCH] More fixes for distance field paths Disables use of SDFs for very small paths (because of blurring) and adds a border of 1 pixel in device space to handle antialiasing. BUG=chromium:677889 Change-Id: Icd2f7e80323b1255f8de52b97360e9a2d995c765 Reviewed-on: https://skia-review.googlesource.com/6895 Reviewed-by: Brian Salomon Commit-Queue: Jim Van Verth --- gm/pathfill.cpp | 50 +++++++++++++++++++ src/gpu/ops/GrAADistanceFieldPathRenderer.cpp | 71 ++++++++++++++++----------- src/gpu/ops/GrAADistanceFieldPathRenderer.h | 5 +- 3 files changed, 95 insertions(+), 31 deletions(-) diff --git a/gm/pathfill.cpp b/gm/pathfill.cpp index da0efea..2562e7c 100644 --- a/gm/pathfill.cpp +++ b/gm/pathfill.cpp @@ -140,6 +140,49 @@ static SkScalar make_line(SkPath* path) { return SkIntToScalar(40); } +static SkScalar make_info(SkPath* path) { + path->moveTo(24, 4); + path->cubicTo(12.94999980926514f, + 4, + 4, + 12.94999980926514f, + 4, + 24); + path->cubicTo(4, + 35.04999923706055f, + 12.94999980926514f, + 44, + 24, + 44); + path->cubicTo(35.04999923706055f, + 44, + 44, + 35.04999923706055f, + 44, + 24); + path->cubicTo(44, + 12.95000076293945f, + 35.04999923706055f, + 4, + 24, + 4); + path->close(); + path->moveTo(26, 34); + path->lineTo(22, 34); + path->lineTo(22, 22); + path->lineTo(26, 22); + path->lineTo(26, 34); + path->close(); + path->moveTo(26, 18); + path->lineTo(22, 18); + path->lineTo(22, 14); + path->lineTo(26, 14); + path->lineTo(26, 18); + path->close(); + + return SkIntToScalar(44); +} + constexpr MakePathProc gProcs[] = { make_frame, make_triangle, @@ -158,11 +201,14 @@ constexpr MakePathProc gProcs[] = { class PathFillGM : public skiagm::GM { SkPath fPath[N]; SkScalar fDY[N]; + SkPath fInfoPath; protected: void onOnceBeforeDraw() override { for (size_t i = 0; i < N; i++) { fDY[i] = gProcs[i](&fPath[i]); } + + (void) make_info(&fInfoPath); } @@ -182,6 +228,10 @@ protected: canvas->drawPath(fPath[i], paint); canvas->translate(SkIntToScalar(0), fDY[i]); } + + canvas->scale(0.300000011920929f, 0.300000011920929f); + canvas->translate(50, 50); + canvas->drawPath(fInfoPath, paint); } private: diff --git a/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp b/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp index 0cf4c00..d025c94 100644 --- a/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp @@ -39,6 +39,7 @@ static int g_NumFreedShapes = 0; #endif // mip levels +static const int kMinSize = 16; static const int kSmallMIP = 32; static const int kMediumMIP = 73; static const int kLargeMIP = 162; @@ -107,14 +108,17 @@ bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c return false; } - // 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 + // Only support paths with bounds within kMediumMIP by kMediumMIP, + // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP. + // For clarity, the original or scaled path should be at least kMinSize by kMinSize. + // TODO: revisit this last criteria with Joel's patch. + // The goal is to accelerate rendering of lots of small paths that may be scaling. SkScalar maxScale = args.fViewMatrix->getMaxScale(); SkRect bounds = args.fShape->styledBounds(); SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); - return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP; + return maxDim <= kMediumMIP && + maxDim * maxScale >= kMinSize && maxDim * maxScale <= 2.0f*kLargeMIP; } //////////////////////////////////////////////////////////////////////////////// @@ -399,29 +403,12 @@ private: // set the bounds rect to the original bounds shapeData->fBounds = bounds; - // set up texture coordinates - SkScalar texLeft = bounds.fLeft; - SkScalar texTop = bounds.fTop; - SkScalar texRight = bounds.fRight; - SkScalar texBottom = bounds.fBottom; - - // transform original path's bounds to texture space - texLeft *= scale; - texTop *= scale; - texRight *= scale; - texBottom *= scale; + // set up path to texture coordinate transform + shapeData->fScale = scale; dx -= SK_DistanceFieldPad + kAntiAliasPad; dy -= SK_DistanceFieldPad + kAntiAliasPad; - texLeft += atlasLocation.fX - dx; - texTop += atlasLocation.fY - dy; - texRight += atlasLocation.fX - dx; - texBottom += atlasLocation.fY - dy; - - GrTexture* texture = atlas->getTexture(); - shapeData->fTexCoords.setLTRB(texLeft / texture->width(), - texTop / texture->height(), - texRight / texture->width(), - texBottom / texture->height()); + shapeData->fTranslate.fX = atlasLocation.fX - dx; + shapeData->fTranslate.fY = atlasLocation.fY - dy; fShapeCache->add(shapeData); fShapeList->addToTail(shapeData); @@ -440,10 +427,15 @@ private: const ShapeData* shapeData) const { SkPoint* positions = reinterpret_cast(offset); + // outset bounds to include ~1 pixel of AA in device space + SkRect bounds = shapeData->fBounds; + SkScalar outset = SkScalarInvert(maxScale); + bounds.outset(outset, outset); + // vertex positions // TODO make the vertex attributes a struct - positions->setRectFan(shapeData->fBounds.left(), shapeData->fBounds.top(), - shapeData->fBounds.right(), shapeData->fBounds.bottom(), vertexStride); + positions->setRectFan(bounds.left(), bounds.top(), bounds.right(), bounds.bottom(), + vertexStride); // colors for (int i = 0; i < kVerticesPerQuad; i++) { @@ -451,11 +443,32 @@ private: *colorPtr = color; } + // set up texture coordinates + SkScalar texLeft = bounds.fLeft; + SkScalar texTop = bounds.fTop; + SkScalar texRight = bounds.fRight; + SkScalar texBottom = bounds.fBottom; + + // transform original path's bounds to texture space + SkScalar scale = shapeData->fScale; + const SkVector& translate = shapeData->fTranslate; + texLeft *= scale; + texTop *= scale; + texRight *= scale; + texBottom *= scale; + texLeft += translate.fX; + texTop += translate.fY; + texRight += translate.fX; + texBottom += translate.fY; + // vertex texture coords // TODO make these int16_t SkPoint* textureCoords = (SkPoint*)(offset + sizeof(SkPoint) + sizeof(GrColor)); - textureCoords->setRectFan(shapeData->fTexCoords.left(), shapeData->fTexCoords.top(), - shapeData->fTexCoords.right(), shapeData->fTexCoords.bottom(), + GrTexture* texture = atlas->getTexture(); + textureCoords->setRectFan(texLeft / texture->width(), + texTop / texture->height(), + texRight / texture->width(), + texBottom / texture->height(), vertexStride); } diff --git a/src/gpu/ops/GrAADistanceFieldPathRenderer.h b/src/gpu/ops/GrAADistanceFieldPathRenderer.h index 5d34807..202b114 100644 --- a/src/gpu/ops/GrAADistanceFieldPathRenderer.h +++ b/src/gpu/ops/GrAADistanceFieldPathRenderer.h @@ -71,8 +71,9 @@ private: }; Key fKey; GrDrawOpAtlas::AtlasID fID; - SkRect fBounds; - SkRect fTexCoords; + SkRect fBounds; + SkScalar fScale; + SkVector fTranslate; SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeData); static inline const Key& GetKey(const ShapeData& data) { -- 2.7.4