| 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 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 SkDELETE(fAtlas); | 60 SkDELETE(fAtlas); |
| 61 | 61 |
| 62 #ifdef DF_PATH_TRACKING | 62 #ifdef DF_PATH_TRACKING |
| 63 SkDebugf("Cached paths: %d, freed paths: %d\n", g_NumCachedPaths, g_NumFreed
Paths); | 63 SkDebugf("Cached paths: %d, freed paths: %d\n", g_NumCachedPaths, g_NumFreed
Paths); |
| 64 #endif | 64 #endif |
| 65 } | 65 } |
| 66 | 66 |
| 67 //////////////////////////////////////////////////////////////////////////////// | 67 //////////////////////////////////////////////////////////////////////////////// |
| 68 bool GrAADistanceFieldPathRenderer::canDrawPath(const GrDrawTarget* target, | 68 bool GrAADistanceFieldPathRenderer::canDrawPath(const GrDrawTarget* target, |
| 69 const GrDrawState* drawState, | 69 const GrDrawState* drawState, |
| 70 const SkMatrix& viewMatrix, |
| 70 const SkPath& path, | 71 const SkPath& path, |
| 71 const SkStrokeRec& stroke, | 72 const SkStrokeRec& stroke, |
| 72 bool antiAlias) const { | 73 bool antiAlias) const { |
| 73 | 74 |
| 74 // TODO: Support inverse fill | 75 // TODO: Support inverse fill |
| 75 // TODO: Support strokes | 76 // TODO: Support strokes |
| 76 if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInver
seFillType() | 77 if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInver
seFillType() |
| 77 || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) { | 78 || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) { |
| 78 return false; | 79 return false; |
| 79 } | 80 } |
| 80 | 81 |
| 81 // currently don't support perspective | 82 // currently don't support perspective |
| 82 const SkMatrix& vm = drawState->getViewMatrix(); | 83 if (viewMatrix.hasPerspective()) { |
| 83 if (vm.hasPerspective()) { | |
| 84 return false; | 84 return false; |
| 85 } | 85 } |
| 86 | 86 |
| 87 // only support paths smaller than 64x64, scaled to less than 256x256 | 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 | 88 // the goal is to accelerate rendering of lots of small paths that may be sc
aling |
| 89 SkScalar maxScale = vm.getMaxScale(); | 89 SkScalar maxScale = viewMatrix.getMaxScale(); |
| 90 const SkRect& bounds = path.getBounds(); | 90 const SkRect& bounds = path.getBounds(); |
| 91 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); | 91 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); |
| 92 return maxDim < 64.f && maxDim*maxScale < 256.f; | 92 return maxDim < 64.f && maxDim*maxScale < 256.f; |
| 93 } | 93 } |
| 94 | 94 |
| 95 | 95 |
| 96 GrPathRenderer::StencilSupport | 96 GrPathRenderer::StencilSupport |
| 97 GrAADistanceFieldPathRenderer::onGetStencilSupport(const GrDrawTarget*, | 97 GrAADistanceFieldPathRenderer::onGetStencilSupport(const GrDrawTarget*, |
| 98 const GrDrawState*, | 98 const GrDrawState*, |
| 99 const SkPath&, | 99 const SkPath&, |
| 100 const SkStrokeRec&) const { | 100 const SkStrokeRec&) const { |
| 101 return GrPathRenderer::kNoSupport_StencilSupport; | 101 return GrPathRenderer::kNoSupport_StencilSupport; |
| 102 } | 102 } |
| 103 | 103 |
| 104 //////////////////////////////////////////////////////////////////////////////// | 104 //////////////////////////////////////////////////////////////////////////////// |
| 105 | 105 |
| 106 bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target, | 106 bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target, |
| 107 GrDrawState* drawState, | 107 GrDrawState* drawState, |
| 108 GrColor color, | 108 GrColor color, |
| 109 const SkMatrix& viewMatrix, |
| 109 const SkPath& path, | 110 const SkPath& path, |
| 110 const SkStrokeRec& stroke, | 111 const SkStrokeRec& stroke, |
| 111 bool antiAlias) { | 112 bool antiAlias) { |
| 112 // we've already bailed on inverse filled paths, so this is safe | 113 // we've already bailed on inverse filled paths, so this is safe |
| 113 if (path.isEmpty()) { | 114 if (path.isEmpty()) { |
| 114 return true; | 115 return true; |
| 115 } | 116 } |
| 116 | 117 |
| 117 SkASSERT(fContext); | 118 SkASSERT(fContext); |
| 118 | 119 |
| 119 // get mip level | 120 // get mip level |
| 120 const SkMatrix& vm = drawState->getViewMatrix(); | 121 SkScalar maxScale = viewMatrix.getMaxScale(); |
| 121 SkScalar maxScale = vm.getMaxScale(); | |
| 122 const SkRect& bounds = path.getBounds(); | 122 const SkRect& bounds = path.getBounds(); |
| 123 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); | 123 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); |
| 124 SkScalar size = maxScale*maxDim; | 124 SkScalar size = maxScale*maxDim; |
| 125 uint32_t desiredDimension; | 125 uint32_t desiredDimension; |
| 126 if (size <= kSmallMIP) { | 126 if (size <= kSmallMIP) { |
| 127 desiredDimension = kSmallMIP; | 127 desiredDimension = kSmallMIP; |
| 128 } else if (size <= kMediumMIP) { | 128 } else if (size <= kMediumMIP) { |
| 129 desiredDimension = kMediumMIP; | 129 desiredDimension = kMediumMIP; |
| 130 } else { | 130 } else { |
| 131 desiredDimension = kLargeMIP; | 131 desiredDimension = kLargeMIP; |
| 132 } | 132 } |
| 133 | 133 |
| 134 // check to see if path is cached | 134 // check to see if path is cached |
| 135 // TODO: handle stroked vs. filled version of same path | 135 // TODO: handle stroked vs. filled version of same path |
| 136 PathData::Key key = { path.getGenerationID(), desiredDimension }; | 136 PathData::Key key = { path.getGenerationID(), desiredDimension }; |
| 137 PathData* pathData = fPathCache.find(key); | 137 PathData* pathData = fPathCache.find(key); |
| 138 if (NULL == pathData) { | 138 if (NULL == pathData) { |
| 139 SkScalar scale = desiredDimension/maxDim; | 139 SkScalar scale = desiredDimension/maxDim; |
| 140 pathData = this->addPathToAtlas(path, stroke, antiAlias, desiredDimensio
n, scale); | 140 pathData = this->addPathToAtlas(path, stroke, antiAlias, desiredDimensio
n, scale); |
| 141 if (NULL == pathData) { | 141 if (NULL == pathData) { |
| 142 return false; | 142 return false; |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 | 145 |
| 146 // use signed distance field to render | 146 // use signed distance field to render |
| 147 return this->internalDrawPath(target, drawState, color, path, pathData); | 147 return this->internalDrawPath(target, drawState, color, viewMatrix, path, pa
thData); |
| 148 } | 148 } |
| 149 | 149 |
| 150 // padding around path bounds to allow for antialiased pixels | 150 // padding around path bounds to allow for antialiased pixels |
| 151 const SkScalar kAntiAliasPad = 1.0f; | 151 const SkScalar kAntiAliasPad = 1.0f; |
| 152 | 152 |
| 153 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
oAtlas( | 153 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
oAtlas( |
| 154 const Sk
Path& path, | 154 const Sk
Path& path, |
| 155 const Sk
StrokeRec& stroke, | 155 const Sk
StrokeRec& stroke, |
| 156 bool ant
iAlias, | 156 bool ant
iAlias, |
| 157 uint32_t
dimension, | 157 uint32_t
dimension, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 | 301 |
| 302 // tell the atlas to free the plot | 302 // tell the atlas to free the plot |
| 303 GrAtlas::RemovePlot(&fPlotUsage, plot); | 303 GrAtlas::RemovePlot(&fPlotUsage, plot); |
| 304 | 304 |
| 305 return true; | 305 return true; |
| 306 } | 306 } |
| 307 | 307 |
| 308 bool GrAADistanceFieldPathRenderer::internalDrawPath(GrDrawTarget* target, | 308 bool GrAADistanceFieldPathRenderer::internalDrawPath(GrDrawTarget* target, |
| 309 GrDrawState* drawState, | 309 GrDrawState* drawState, |
| 310 GrColor color, | 310 GrColor color, |
| 311 const SkMatrix& viewMatrix, |
| 311 const SkPath& path, | 312 const SkPath& path, |
| 312 const PathData* pathData) { | 313 const PathData* pathData) { |
| 313 GrTexture* texture = fAtlas->getTexture(); | 314 GrTexture* texture = fAtlas->getTexture(); |
| 314 GrDrawState::AutoRestoreEffects are(drawState); | 315 GrDrawState::AutoRestoreEffects are(drawState); |
| 315 | 316 |
| 316 SkASSERT(pathData->fPlot); | 317 SkASSERT(pathData->fPlot); |
| 317 GrDrawTarget::DrawToken drawToken = target->getCurrentDrawToken(); | 318 GrDrawTarget::DrawToken drawToken = target->getCurrentDrawToken(); |
| 318 pathData->fPlot->setDrawToken(drawToken); | 319 pathData->fPlot->setDrawToken(drawToken); |
| 319 | 320 |
| 320 // set up any flags | 321 // set up any flags |
| 321 uint32_t flags = 0; | 322 uint32_t flags = 0; |
| 322 const SkMatrix& vm = drawState->getViewMatrix(); | 323 flags |= viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0
; |
| 323 flags |= vm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; | |
| 324 | 324 |
| 325 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_
FilterMode); | 325 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_
FilterMode); |
| 326 if (flags != fEffectFlags || fCachedGeometryProcessor->color() != color) { | 326 if (flags != fEffectFlags || fCachedGeometryProcessor->color() != color || |
| 327 !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(viewMatrix)) { |
| 327 fCachedGeometryProcessor.reset(GrDistanceFieldNoGammaTextureEffect::Crea
te(color, | 328 fCachedGeometryProcessor.reset(GrDistanceFieldNoGammaTextureEffect::Crea
te(color, |
| 329
viewMatrix, |
| 328
texture, | 330
texture, |
| 329
params, | 331
params, |
| 330
flags, | 332
flags, |
| 331
false)); | 333
false)); |
| 332 fEffectFlags = flags; | 334 fEffectFlags = flags; |
| 333 } | 335 } |
| 334 | 336 |
| 335 void* vertices = NULL; | 337 void* vertices = NULL; |
| 336 bool success = target->reserveVertexAndIndexSpace(4, | 338 bool success = target->reserveVertexAndIndexSpace(4, |
| 337 fCachedGeometryProcessor->
getVertexStride(), | 339 fCachedGeometryProcessor->
getVertexStride(), |
| (...skipping 25 matching lines...) Expand all Loading... |
| 363 | 365 |
| 364 // vertex texture coords | 366 // vertex texture coords |
| 365 intptr_t intPtr = reinterpret_cast<intptr_t>(positions); | 367 intptr_t intPtr = reinterpret_cast<intptr_t>(positions); |
| 366 SkPoint* textureCoords = reinterpret_cast<SkPoint*>(intPtr + vertSize - size
of(SkPoint)); | 368 SkPoint* textureCoords = reinterpret_cast<SkPoint*>(intPtr + vertSize - size
of(SkPoint)); |
| 367 textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFix
edX(tx)), | 369 textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFix
edX(tx)), |
| 368 SkFixedToFloat(texture->texturePriv().normalizeFix
edY(ty)), | 370 SkFixedToFloat(texture->texturePriv().normalizeFix
edY(ty)), |
| 369 SkFixedToFloat(texture->texturePriv().normalizeFix
edX(tx + tw)), | 371 SkFixedToFloat(texture->texturePriv().normalizeFix
edX(tx + tw)), |
| 370 SkFixedToFloat(texture->texturePriv().normalizeFix
edY(ty + th)), | 372 SkFixedToFloat(texture->texturePriv().normalizeFix
edY(ty + th)), |
| 371 vertSize); | 373 vertSize); |
| 372 | 374 |
| 373 vm.mapRect(&r); | 375 viewMatrix.mapRect(&r); |
| 374 target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 376 target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |
| 375 target->drawIndexedInstances(drawState, fCachedGeometryProcessor.get(), | 377 target->drawIndexedInstances(drawState, fCachedGeometryProcessor.get(), |
| 376 kTriangles_GrPrimitiveType, 1, 4, 6, &r); | 378 kTriangles_GrPrimitiveType, 1, 4, 6, &r); |
| 377 target->resetVertexSource(); | 379 target->resetVertexSource(); |
| 378 | 380 |
| 379 return true; | 381 return true; |
| 380 } | 382 } |
| 381 | 383 |
| OLD | NEW |