| Index: src/gpu/GrAADistanceFieldPathRenderer.cpp
|
| diff --git a/src/gpu/GrAADistanceFieldPathRenderer.cpp b/src/gpu/GrAADistanceFieldPathRenderer.cpp
|
| index 95675e4fce6b35bc3489ce7af9db66dfec54b06d..fdd0f68afeda7b58a2f9c59d1ccc289aa054ff64 100755
|
| --- a/src/gpu/GrAADistanceFieldPathRenderer.cpp
|
| +++ b/src/gpu/GrAADistanceFieldPathRenderer.cpp
|
| @@ -20,7 +20,7 @@
|
| #include "SkRTConf.h"
|
|
|
| #define ATLAS_TEXTURE_WIDTH 1024
|
| -#define ATLAS_TEXTURE_HEIGHT 1024
|
| +#define ATLAS_TEXTURE_HEIGHT 2048
|
| #define PLOT_WIDTH 256
|
| #define PLOT_HEIGHT 256
|
|
|
| @@ -35,6 +35,11 @@ static int g_NumCachedPaths = 0;
|
| static int g_NumFreedPaths = 0;
|
| #endif
|
|
|
| +// mip levels
|
| +static const int kSmallMIP = 32;
|
| +static const int kMediumMIP = 64;
|
| +static const int kLargeMIP = 128;
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| GrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer(GrContext* context)
|
| : fContext(context)
|
| @@ -72,16 +77,19 @@ bool GrAADistanceFieldPathRenderer::canDrawPath(const SkPath& path,
|
| return false;
|
| }
|
|
|
| - // currently don't support perspective or scaling more than 3x
|
| + // currently don't support perspective
|
| const GrDrawState& drawState = target->getDrawState();
|
| const SkMatrix& vm = drawState.getViewMatrix();
|
| - if (vm.hasPerspective() || vm.getMaxScale() > 3.0f) {
|
| + if (vm.hasPerspective()) {
|
| return false;
|
| }
|
|
|
| - // only support paths smaller than 64 x 64
|
| + // 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 = vm.getMaxScale();
|
| const SkRect& bounds = path.getBounds();
|
| - return bounds.width() < 64.f && bounds.height() < 64.f;
|
| + SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
|
| + return maxDim < 64.f && maxDim*maxScale < 256.f;
|
| }
|
|
|
|
|
| @@ -112,11 +120,29 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(const SkPath& path,
|
|
|
| SkASSERT(fContext);
|
|
|
| + // get mip level
|
| + const GrDrawState& drawState = target->getDrawState();
|
| + const SkMatrix& vm = drawState.getViewMatrix();
|
| + SkScalar maxScale = vm.getMaxScale();
|
| + const SkRect& bounds = path.getBounds();
|
| + SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
|
| + SkScalar size = maxScale*maxDim;
|
| + uint32_t desiredDimension;
|
| + if (size <= kSmallMIP) {
|
| + desiredDimension = kSmallMIP;
|
| + } else if (size <= kMediumMIP) {
|
| + desiredDimension = kMediumMIP;
|
| + } else {
|
| + desiredDimension = kLargeMIP;
|
| + }
|
| +
|
| // check to see if path is cached
|
| // TODO: handle stroked vs. filled version of same path
|
| - PathData* pathData = fPathCache.find(path.getGenerationID());
|
| + PathData::Key key = { path.getGenerationID(), desiredDimension };
|
| + PathData* pathData = fPathCache.find(key);
|
| if (NULL == pathData) {
|
| - pathData = this->addPathToAtlas(path, stroke, antiAlias);
|
| + SkScalar scale = desiredDimension/maxDim;
|
| + pathData = this->addPathToAtlas(path, stroke, antiAlias, desiredDimension, scale);
|
| if (NULL == pathData) {
|
| return false;
|
| }
|
| @@ -126,15 +152,15 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(const SkPath& path,
|
| return this->internalDrawPath(path, pathData, target);
|
| }
|
|
|
| -// factor used to scale the path prior to building distance field
|
| -const SkScalar kScaleFactor = 2.0f;
|
| // padding around path bounds to allow for antialiased pixels
|
| const SkScalar kAntiAliasPad = 1.0f;
|
|
|
| GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathToAtlas(
|
| const SkPath& path,
|
| const SkStrokeRec& stroke,
|
| - bool antiAlias) {
|
| + bool antiAlias,
|
| + uint32_t dimension,
|
| + SkScalar scale) {
|
|
|
| // generate distance field and add to atlas
|
| if (NULL == fAtlas) {
|
| @@ -151,11 +177,11 @@ GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
|
|
|
| // generate bounding rect for bitmap draw
|
| SkRect scaledBounds = bounds;
|
| - // scale up to improve maxification range
|
| - scaledBounds.fLeft *= kScaleFactor;
|
| - scaledBounds.fTop *= kScaleFactor;
|
| - scaledBounds.fRight *= kScaleFactor;
|
| - scaledBounds.fBottom *= kScaleFactor;
|
| + // scale to mip level size
|
| + scaledBounds.fLeft *= scale;
|
| + scaledBounds.fTop *= scale;
|
| + scaledBounds.fRight *= scale;
|
| + scaledBounds.fBottom *= scale;
|
| // move the origin to an integer boundary (gives better results)
|
| SkScalar dx = SkScalarFraction(scaledBounds.fLeft);
|
| SkScalar dy = SkScalarFraction(scaledBounds.fTop);
|
| @@ -171,7 +197,7 @@ GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
|
| // draw path to bitmap
|
| SkMatrix drawMatrix;
|
| drawMatrix.setTranslate(-bounds.left(), -bounds.top());
|
| - drawMatrix.postScale(kScaleFactor, kScaleFactor);
|
| + drawMatrix.postScale(scale, scale);
|
| drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad);
|
| GrSWMaskHelper helper(fContext);
|
|
|
| @@ -226,7 +252,9 @@ GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
|
| HAS_ATLAS:
|
| // add to cache
|
| PathData* pathData = SkNEW(PathData);
|
| - pathData->fGenID = path.getGenerationID();
|
| + pathData->fKey.fGenID = path.getGenerationID();
|
| + pathData->fKey.fDimension = dimension;
|
| + pathData->fScale = scale;
|
| pathData->fPlot = plot;
|
| // change the scaled rect to match the size of the inset distance field
|
| scaledBounds.fRight = scaledBounds.fLeft +
|
| @@ -267,7 +295,7 @@ bool GrAADistanceFieldPathRenderer::freeUnusedPlot() {
|
| while ((pathData = iter.get())) {
|
| iter.next();
|
| if (plot == pathData->fPlot) {
|
| - fPathCache.remove(pathData->fGenID);
|
| + fPathCache.remove(pathData->fKey);
|
| fPathList.remove(pathData);
|
| SkDELETE(pathData);
|
| #ifdef DF_PATH_TRACKING
|
| @@ -305,7 +333,7 @@ bool GrAADistanceFieldPathRenderer::internalDrawPath(const SkPath& path,
|
| SkScalar width = pathData->fBounds.width();
|
| SkScalar height = pathData->fBounds.height();
|
|
|
| - SkScalar invScale = 1.0f/kScaleFactor;
|
| + SkScalar invScale = 1.0f/pathData->fScale;
|
| dx *= invScale;
|
| dy *= invScale;
|
| width *= invScale;
|
|
|