From f9e678d6964bc5a6c2b38edbc36d9f23cf96c37f Mon Sep 17 00:00:00 2001 From: Jim Van Verth Date: Wed, 15 Feb 2017 15:46:52 -0500 Subject: Use SDF path miplevels based on the original path's size Should produce sharper results than arbitrary fixed sizes. Adds a new test to pathfill GM. Was: https://skia-review.googlesource.com/c/8328/ BUG=chromium:682918, skia:6238 Change-Id: Ia62ea5ce6b4a5ac2b8b51d06d57dc951d6c340b8 Reviewed-on: https://skia-review.googlesource.com/8384 Reviewed-by: Brian Salomon Commit-Queue: Jim Van Verth --- src/gpu/ops/GrAADistanceFieldPathRenderer.cpp | 53 +++++++++++++++------------ 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'src/gpu/ops') diff --git a/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp b/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp index a72f7dc40f..7131e18a46 100644 --- a/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp @@ -10,6 +10,7 @@ #include "GrBuffer.h" #include "GrContext.h" +#include "GrDistanceFieldGenFromVector.h" #include "GrDrawOpTest.h" #include "GrOpFlushState.h" #include "GrPipelineBuilder.h" @@ -20,10 +21,9 @@ #include "effects/GrDistanceFieldGeoProc.h" #include "ops/GrMeshDrawOp.h" -#include "SkPathOps.h" #include "SkAutoMalloc.h" #include "SkDistanceFieldGen.h" -#include "GrDistanceFieldGenFromVector.h" +#include "SkPathOps.h" #define ATLAS_TEXTURE_WIDTH 2048 #define ATLAS_TEXTURE_HEIGHT 2048 @@ -39,9 +39,11 @@ static int g_NumFreedShapes = 0; #endif // mip levels -static const int kSmallMIP = 32; -static const int kMediumMIP = 73; -static const int kLargeMIP = 162; +static const SkScalar kMaxMIP = 162; + +static const SkScalar kMaxDim = 73; +static const SkScalar kMinSize = 8; +static const SkScalar kMaxSize = 2*kMaxMIP; // Callback to clear out internal path cache when eviction occurs void GrAADistanceFieldPathRenderer::HandleEviction(GrDrawOpAtlas::AtlasID id, void* pr) { @@ -107,14 +109,20 @@ 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. + // Only support paths with bounds within kMaxDim by kMaxDim, + // scaled to have bounds within kMaxSize by kMaxSize. // The goal is to accelerate rendering of lots of small paths that may be scaling. - SkScalar maxScale = args.fViewMatrix->getMaxScale(); + SkScalar scaleFactors[2]; + if (!args.fViewMatrix->getMinMaxScales(scaleFactors)) { + return false; + } SkRect bounds = args.fShape->styledBounds(); + SkScalar minDim = SkMinScalar(bounds.width(), bounds.height()); SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); + SkScalar minSize = minDim * scaleFactors[0]; + SkScalar maxSize = maxDim * scaleFactors[1]; - return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP; + return maxDim <= kMaxDim && kMinSize <= minSize && maxSize <= kMaxSize; } //////////////////////////////////////////////////////////////////////////////// @@ -240,23 +248,22 @@ private: SkScalar maxScale = this->viewMatrix().getMaxScale(); const SkRect& bounds = args.fShape.bounds(); SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); - SkScalar size = maxScale * maxDim; - SkScalar desiredDimension; - // For minimizing (or the common case of identity) transforms, we try to - // create the DF at the appropriately sized native src-space path resolution. + // We try to create the DF at a power of two scaled path resolution (1/2, 1, 2, 4, etc) // In the majority of cases this will yield a crisper rendering. - if (size <= maxDim && maxDim < kSmallMIP) { - desiredDimension = maxDim; - } else if (size <= kSmallMIP) { - desiredDimension = kSmallMIP; - } else if (size <= maxDim) { - desiredDimension = maxDim; - } else if (size <= kMediumMIP) { - desiredDimension = kMediumMIP; - } else { - desiredDimension = kLargeMIP; + SkScalar mipScale = 1.0f; + // Our mipscale is the maxScale clamped to the next highest power of 2 + if (maxScale < SK_ScalarHalf) { + SkScalar log = SkScalarFloorToScalar(SkScalarLog2(SkScalarInvert(maxScale))); + mipScale = SkScalarPow(2, -log); + } else if (maxScale > SK_Scalar1) { + SkScalar log = SkScalarCeilToScalar(SkScalarLog2(maxScale)); + mipScale = SkScalarPow(2, log); } + SkScalar mipSize = mipScale*maxDim; + SkASSERT(maxScale * maxDim <= mipSize); + SkScalar desiredDimension = SkTMin(mipSize, kMaxMIP); + // check to see if path is cached ShapeData::Key key(args.fShape, SkScalarCeilToInt(desiredDimension)); ShapeData* shapeData = fShapeCache->find(key); -- cgit v1.2.3