| OLD | NEW | 
|    1  |    1  | 
|    2 /* |    2 /* | 
|    3  * Copyright 2014 Google Inc. |    3  * Copyright 2014 Google Inc. | 
|    4  * |    4  * | 
|    5  * Use of this source code is governed by a BSD-style license that can be |    5  * Use of this source code is governed by a BSD-style license that can be | 
|    6  * found in the LICENSE file. |    6  * found in the LICENSE file. | 
|    7  */ |    7  */ | 
|    8  |    8  | 
|    9 #include "GrAADistanceFieldPathRenderer.h" |    9 #include "GrAADistanceFieldPathRenderer.h" | 
|   10  |   10  | 
|   11 #include "GrAtlas.h" |   11 #include "GrAtlas.h" | 
|   12 #include "GrContext.h" |   12 #include "GrContext.h" | 
|   13 #include "GrDrawState.h" |   13 #include "GrDrawState.h" | 
|   14 #include "GrSurfacePriv.h" |   14 #include "GrSurfacePriv.h" | 
|   15 #include "GrSWMaskHelper.h" |   15 #include "GrSWMaskHelper.h" | 
|   16 #include "GrTexturePriv.h" |   16 #include "GrTexturePriv.h" | 
|   17 #include "effects/GrDistanceFieldTextureEffect.h" |   17 #include "effects/GrDistanceFieldTextureEffect.h" | 
|   18  |   18  | 
|   19 #include "SkDistanceFieldGen.h" |   19 #include "SkDistanceFieldGen.h" | 
|   20 #include "SkRTConf.h" |   20 #include "SkRTConf.h" | 
|   21  |   21  | 
|   22 #define ATLAS_TEXTURE_WIDTH 1024 |   22 #define ATLAS_TEXTURE_WIDTH 1024 | 
|   23 #define ATLAS_TEXTURE_HEIGHT 1024 |   23 #define ATLAS_TEXTURE_HEIGHT 2048 | 
|   24 #define PLOT_WIDTH  256 |   24 #define PLOT_WIDTH  256 | 
|   25 #define PLOT_HEIGHT 256 |   25 #define PLOT_HEIGHT 256 | 
|   26  |   26  | 
|   27 #define NUM_PLOTS_X   (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH) |   27 #define NUM_PLOTS_X   (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH) | 
|   28 #define NUM_PLOTS_Y   (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT) |   28 #define NUM_PLOTS_Y   (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT) | 
|   29  |   29  | 
|   30 SK_CONF_DECLARE(bool, c_DumpPathCache, "gpu.dumpPathCache", false, |   30 SK_CONF_DECLARE(bool, c_DumpPathCache, "gpu.dumpPathCache", false, | 
|   31                 "Dump the contents of the path cache before every purge."); |   31                 "Dump the contents of the path cache before every purge."); | 
|   32  |   32  | 
|   33 #ifdef DF_PATH_TRACKING |   33 #ifdef DF_PATH_TRACKING | 
|   34 static int g_NumCachedPaths = 0; |   34 static int g_NumCachedPaths = 0; | 
|   35 static int g_NumFreedPaths = 0; |   35 static int g_NumFreedPaths = 0; | 
|   36 #endif |   36 #endif | 
|   37  |   37  | 
 |   38 // mip levels | 
 |   39 static const int kSmallMIP = 32; | 
 |   40 static const int kMediumMIP = 64; | 
 |   41 static const int kLargeMIP = 128; | 
 |   42  | 
|   38 //////////////////////////////////////////////////////////////////////////////// |   43 //////////////////////////////////////////////////////////////////////////////// | 
|   39 GrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer(GrContext* context) |   44 GrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer(GrContext* context) | 
|   40     : fContext(context) |   45     : fContext(context) | 
|   41     , fAtlas(NULL) |   46     , fAtlas(NULL) | 
|   42     , fEffectFlags(kInvalid_DistanceFieldEffectFlag) { |   47     , fEffectFlags(kInvalid_DistanceFieldEffectFlag) { | 
|   43 } |   48 } | 
|   44  |   49  | 
|   45 GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() { |   50 GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() { | 
|   46     PathDataList::Iter iter; |   51     PathDataList::Iter iter; | 
|   47     iter.init(fPathList, PathDataList::Iter::kHead_IterStart); |   52     iter.init(fPathList, PathDataList::Iter::kHead_IterStart); | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|   65                                                 const GrDrawTarget* target, |   70                                                 const GrDrawTarget* target, | 
|   66                                                 bool antiAlias) const { |   71                                                 bool antiAlias) const { | 
|   67      |   72      | 
|   68     // TODO: Support inverse fill |   73     // TODO: Support inverse fill | 
|   69     // TODO: Support strokes |   74     // TODO: Support strokes | 
|   70     if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInver
     seFillType() |   75     if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInver
     seFillType() | 
|   71         || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) { |   76         || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) { | 
|   72         return false; |   77         return false; | 
|   73     } |   78     } | 
|   74  |   79  | 
|   75     // currently don't support perspective or scaling more than 3x |   80     // currently don't support perspective | 
|   76     const GrDrawState& drawState = target->getDrawState(); |   81     const GrDrawState& drawState = target->getDrawState(); | 
|   77     const SkMatrix& vm = drawState.getViewMatrix(); |   82     const SkMatrix& vm = drawState.getViewMatrix(); | 
|   78     if (vm.hasPerspective() || vm.getMaxScale() > 3.0f) { |   83     if (vm.hasPerspective()) { | 
|   79         return false; |   84         return false; | 
|   80     } |   85     } | 
|   81      |   86      | 
|   82     // only support paths smaller than 64 x 64 |   87     // only support paths smaller than 64x64, scaled to less than 256x256 | 
 |   88     // the goal is to accelerate rendering of lots of small paths that may be sc
     aling | 
 |   89     SkScalar maxScale = vm.getMaxScale(); | 
|   83     const SkRect& bounds = path.getBounds(); |   90     const SkRect& bounds = path.getBounds(); | 
|   84     return bounds.width() < 64.f && bounds.height() < 64.f; |   91     SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); | 
 |   92     return maxDim < 64.f && maxDim*maxScale < 256.f; | 
|   85 } |   93 } | 
|   86  |   94  | 
|   87  |   95  | 
|   88 GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSuppor
     t( |   96 GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSuppor
     t( | 
|   89                                                                        const SkP
     ath&, |   97                                                                        const SkP
     ath&, | 
|   90                                                                        const SkS
     trokeRec&, |   98                                                                        const SkS
     trokeRec&, | 
|   91                                                                        const GrD
     rawTarget*) const { |   99                                                                        const GrD
     rawTarget*) const { | 
|   92     return GrPathRenderer::kNoSupport_StencilSupport; |  100     return GrPathRenderer::kNoSupport_StencilSupport; | 
|   93 } |  101 } | 
|   94  |  102  | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  105                                                const SkStrokeRec& stroke, |  113                                                const SkStrokeRec& stroke, | 
|  106                                                GrDrawTarget* target, |  114                                                GrDrawTarget* target, | 
|  107                                                bool antiAlias) { |  115                                                bool antiAlias) { | 
|  108     // we've already bailed on inverse filled paths, so this is safe |  116     // we've already bailed on inverse filled paths, so this is safe | 
|  109     if (path.isEmpty()) { |  117     if (path.isEmpty()) { | 
|  110         return true; |  118         return true; | 
|  111     } |  119     } | 
|  112  |  120  | 
|  113     SkASSERT(fContext); |  121     SkASSERT(fContext); | 
|  114  |  122  | 
 |  123     // get mip level | 
 |  124     const GrDrawState& drawState = target->getDrawState(); | 
 |  125     const SkMatrix& vm = drawState.getViewMatrix(); | 
 |  126     SkScalar maxScale = vm.getMaxScale(); | 
 |  127     const SkRect& bounds = path.getBounds(); | 
 |  128     SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); | 
 |  129     SkScalar size = maxScale*maxDim; | 
 |  130     uint32_t desiredDimension; | 
 |  131     if (size <= kSmallMIP) { | 
 |  132         desiredDimension = kSmallMIP; | 
 |  133     } else if (size <= kMediumMIP) { | 
 |  134         desiredDimension = kMediumMIP; | 
 |  135     } else { | 
 |  136         desiredDimension = kLargeMIP; | 
 |  137     } | 
 |  138  | 
|  115     // check to see if path is cached |  139     // check to see if path is cached | 
|  116     // TODO: handle stroked vs. filled version of same path |  140     // TODO: handle stroked vs. filled version of same path | 
|  117     PathData* pathData = fPathCache.find(path.getGenerationID()); |  141     PathData::Key key = { path.getGenerationID(), desiredDimension }; | 
 |  142     PathData* pathData = fPathCache.find(key); | 
|  118     if (NULL == pathData) { |  143     if (NULL == pathData) { | 
|  119         pathData = this->addPathToAtlas(path, stroke, antiAlias); |  144         SkScalar scale = desiredDimension/maxDim; | 
 |  145         pathData = this->addPathToAtlas(path, stroke, antiAlias, desiredDimensio
     n, scale); | 
|  120         if (NULL == pathData) { |  146         if (NULL == pathData) { | 
|  121             return false; |  147             return false; | 
|  122         } |  148         } | 
|  123     } |  149     } | 
|  124  |  150  | 
|  125     // use signed distance field to render |  151     // use signed distance field to render | 
|  126     return this->internalDrawPath(path, pathData, target); |  152     return this->internalDrawPath(path, pathData, target); | 
|  127 } |  153 } | 
|  128  |  154  | 
|  129 // factor used to scale the path prior to building distance field |  | 
|  130 const SkScalar kScaleFactor = 2.0f; |  | 
|  131 // padding around path bounds to allow for antialiased pixels |  155 // padding around path bounds to allow for antialiased pixels | 
|  132 const SkScalar kAntiAliasPad = 1.0f; |  156 const SkScalar kAntiAliasPad = 1.0f; | 
|  133  |  157  | 
|  134 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
     oAtlas( |  158 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
     oAtlas( | 
|  135                                                                         const Sk
     Path& path, |  159                                                                         const Sk
     Path& path, | 
|  136                                                                         const Sk
     StrokeRec& stroke, |  160                                                                         const Sk
     StrokeRec& stroke, | 
|  137                                                                         bool ant
     iAlias) { |  161                                                                         bool ant
     iAlias, | 
 |  162                                                                         uint32_t
      dimension, | 
 |  163                                                                         SkScalar
      scale) { | 
|  138  |  164  | 
|  139     // generate distance field and add to atlas |  165     // generate distance field and add to atlas | 
|  140     if (NULL == fAtlas) { |  166     if (NULL == fAtlas) { | 
|  141         SkISize textureSize = SkISize::Make(ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_H
     EIGHT); |  167         SkISize textureSize = SkISize::Make(ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_H
     EIGHT); | 
|  142         fAtlas = SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kAlpha_8_GrPixelConfig
     , |  168         fAtlas = SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kAlpha_8_GrPixelConfig
     , | 
|  143                                       kNone_GrSurfaceFlags, textureSize, |  169                                       kNone_GrSurfaceFlags, textureSize, | 
|  144                                       NUM_PLOTS_X, NUM_PLOTS_Y, false)); |  170                                       NUM_PLOTS_X, NUM_PLOTS_Y, false)); | 
|  145         if (NULL == fAtlas) { |  171         if (NULL == fAtlas) { | 
|  146             return NULL; |  172             return NULL; | 
|  147         } |  173         } | 
|  148     } |  174     } | 
|  149      |  175      | 
|  150     const SkRect& bounds = path.getBounds(); |  176     const SkRect& bounds = path.getBounds(); | 
|  151      |  177      | 
|  152     // generate bounding rect for bitmap draw |  178     // generate bounding rect for bitmap draw | 
|  153     SkRect scaledBounds = bounds; |  179     SkRect scaledBounds = bounds; | 
|  154     // scale up to improve maxification range |  180     // scale to mip level size | 
|  155     scaledBounds.fLeft *= kScaleFactor; |  181     scaledBounds.fLeft *= scale; | 
|  156     scaledBounds.fTop *= kScaleFactor; |  182     scaledBounds.fTop *= scale; | 
|  157     scaledBounds.fRight *= kScaleFactor; |  183     scaledBounds.fRight *= scale; | 
|  158     scaledBounds.fBottom *= kScaleFactor; |  184     scaledBounds.fBottom *= scale; | 
|  159     // move the origin to an integer boundary (gives better results) |  185     // move the origin to an integer boundary (gives better results) | 
|  160     SkScalar dx = SkScalarFraction(scaledBounds.fLeft); |  186     SkScalar dx = SkScalarFraction(scaledBounds.fLeft); | 
|  161     SkScalar dy = SkScalarFraction(scaledBounds.fTop); |  187     SkScalar dy = SkScalarFraction(scaledBounds.fTop); | 
|  162     scaledBounds.offset(-dx, -dy); |  188     scaledBounds.offset(-dx, -dy); | 
|  163     // get integer boundary |  189     // get integer boundary | 
|  164     SkIRect devPathBounds; |  190     SkIRect devPathBounds; | 
|  165     scaledBounds.roundOut(&devPathBounds); |  191     scaledBounds.roundOut(&devPathBounds); | 
|  166     // pad to allow room for antialiasing |  192     // pad to allow room for antialiasing | 
|  167     devPathBounds.outset(SkScalarCeilToInt(kAntiAliasPad), SkScalarCeilToInt(kAn
     tiAliasPad)); |  193     devPathBounds.outset(SkScalarCeilToInt(kAntiAliasPad), SkScalarCeilToInt(kAn
     tiAliasPad)); | 
|  168     // move origin to upper left corner |  194     // move origin to upper left corner | 
|  169     devPathBounds.offsetTo(0,0); |  195     devPathBounds.offsetTo(0,0); | 
|  170      |  196      | 
|  171     // draw path to bitmap |  197     // draw path to bitmap | 
|  172     SkMatrix drawMatrix; |  198     SkMatrix drawMatrix; | 
|  173     drawMatrix.setTranslate(-bounds.left(), -bounds.top()); |  199     drawMatrix.setTranslate(-bounds.left(), -bounds.top()); | 
|  174     drawMatrix.postScale(kScaleFactor, kScaleFactor); |  200     drawMatrix.postScale(scale, scale); | 
|  175     drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad); |  201     drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad); | 
|  176     GrSWMaskHelper helper(fContext); |  202     GrSWMaskHelper helper(fContext); | 
|  177      |  203      | 
|  178     if (!helper.init(devPathBounds, &drawMatrix)) { |  204     if (!helper.init(devPathBounds, &drawMatrix)) { | 
|  179         return NULL; |  205         return NULL; | 
|  180     } |  206     } | 
|  181     helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF); |  207     helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF); | 
|  182      |  208      | 
|  183     // generate signed distance field |  209     // generate signed distance field | 
|  184     devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad); |  210     devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad); | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  219                 goto HAS_ATLAS; |  245                 goto HAS_ATLAS; | 
|  220             } |  246             } | 
|  221         } |  247         } | 
|  222              |  248              | 
|  223         return NULL; |  249         return NULL; | 
|  224     } |  250     } | 
|  225      |  251      | 
|  226 HAS_ATLAS: |  252 HAS_ATLAS: | 
|  227     // add to cache |  253     // add to cache | 
|  228     PathData* pathData = SkNEW(PathData); |  254     PathData* pathData = SkNEW(PathData); | 
|  229     pathData->fGenID = path.getGenerationID(); |  255     pathData->fKey.fGenID = path.getGenerationID(); | 
 |  256     pathData->fKey.fDimension = dimension; | 
 |  257     pathData->fScale = scale; | 
|  230     pathData->fPlot = plot; |  258     pathData->fPlot = plot; | 
|  231     // change the scaled rect to match the size of the inset distance field |  259     // change the scaled rect to match the size of the inset distance field | 
|  232     scaledBounds.fRight = scaledBounds.fLeft + |  260     scaledBounds.fRight = scaledBounds.fLeft + | 
|  233         SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset); |  261         SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset); | 
|  234     scaledBounds.fBottom = scaledBounds.fTop + |  262     scaledBounds.fBottom = scaledBounds.fTop + | 
|  235         SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset); |  263         SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset); | 
|  236     // shift the origin to the correct place relative to the distance field |  264     // shift the origin to the correct place relative to the distance field | 
|  237     // need to also restore the fractional translation |  265     // need to also restore the fractional translation | 
|  238     scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + 
     dx, |  266     scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + 
     dx, | 
|  239                         -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + 
     dy); |  267                         -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + 
     dy); | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|  260     } |  288     } | 
|  261     plot->resetRects(); |  289     plot->resetRects(); | 
|  262  |  290  | 
|  263     // remove any paths that use this plot |  291     // remove any paths that use this plot | 
|  264     PathDataList::Iter iter; |  292     PathDataList::Iter iter; | 
|  265     iter.init(fPathList, PathDataList::Iter::kHead_IterStart); |  293     iter.init(fPathList, PathDataList::Iter::kHead_IterStart); | 
|  266     PathData* pathData; |  294     PathData* pathData; | 
|  267     while ((pathData = iter.get())) { |  295     while ((pathData = iter.get())) { | 
|  268         iter.next(); |  296         iter.next(); | 
|  269         if (plot == pathData->fPlot) { |  297         if (plot == pathData->fPlot) { | 
|  270             fPathCache.remove(pathData->fGenID); |  298             fPathCache.remove(pathData->fKey); | 
|  271             fPathList.remove(pathData); |  299             fPathList.remove(pathData); | 
|  272             SkDELETE(pathData); |  300             SkDELETE(pathData); | 
|  273 #ifdef DF_PATH_TRACKING |  301 #ifdef DF_PATH_TRACKING | 
|  274             ++g_NumFreedPaths; |  302             ++g_NumFreedPaths; | 
|  275 #endif |  303 #endif | 
|  276         } |  304         } | 
|  277     } |  305     } | 
|  278          |  306          | 
|  279     // tell the atlas to free the plot |  307     // tell the atlas to free the plot | 
|  280     GrAtlas::RemovePlot(&fPlotUsage, plot); |  308     GrAtlas::RemovePlot(&fPlotUsage, plot); | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|  298                                                        kSDFPathVASize); |  326                                                        kSDFPathVASize); | 
|  299     void* vertices = NULL; |  327     void* vertices = NULL; | 
|  300     bool success = target->reserveVertexAndIndexSpace(4, 0, &vertices, NULL); |  328     bool success = target->reserveVertexAndIndexSpace(4, 0, &vertices, NULL); | 
|  301     GrAlwaysAssert(success); |  329     GrAlwaysAssert(success); | 
|  302      |  330      | 
|  303     SkScalar dx = pathData->fBounds.fLeft; |  331     SkScalar dx = pathData->fBounds.fLeft; | 
|  304     SkScalar dy = pathData->fBounds.fTop; |  332     SkScalar dy = pathData->fBounds.fTop; | 
|  305     SkScalar width = pathData->fBounds.width(); |  333     SkScalar width = pathData->fBounds.width(); | 
|  306     SkScalar height = pathData->fBounds.height(); |  334     SkScalar height = pathData->fBounds.height(); | 
|  307      |  335      | 
|  308     SkScalar invScale = 1.0f/kScaleFactor; |  336     SkScalar invScale = 1.0f/pathData->fScale; | 
|  309     dx *= invScale; |  337     dx *= invScale; | 
|  310     dy *= invScale; |  338     dy *= invScale; | 
|  311     width *= invScale; |  339     width *= invScale; | 
|  312     height *= invScale; |  340     height *= invScale; | 
|  313      |  341      | 
|  314     SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX); |  342     SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX); | 
|  315     SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY); |  343     SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY); | 
|  316     SkFixed tw = SkScalarToFixed(pathData->fBounds.width()); |  344     SkFixed tw = SkScalarToFixed(pathData->fBounds.width()); | 
|  317     SkFixed th = SkScalarToFixed(pathData->fBounds.height()); |  345     SkFixed th = SkScalarToFixed(pathData->fBounds.height()); | 
|  318      |  346      | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|  346     drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); |  374     drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); | 
|  347  |  375  | 
|  348     vm.mapRect(&r); |  376     vm.mapRect(&r); | 
|  349     target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |  377     target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 
|  350     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r); |  378     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r); | 
|  351     target->resetVertexSource(); |  379     target->resetVertexSource(); | 
|  352      |  380      | 
|  353     return true; |  381     return true; | 
|  354 } |  382 } | 
|  355  |  383  | 
| OLD | NEW |