| 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 } | 58 } |
| 59 | 59 |
| 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 SkPath& path, | 68 bool GrAADistanceFieldPathRenderer::canDrawPath(const GrDrawTarget* target, |
| 69 const GrDrawState* drawState, |
| 70 const SkPath& path, |
| 69 const SkStrokeRec& stroke, | 71 const SkStrokeRec& stroke, |
| 70 const GrDrawTarget* target, | |
| 71 bool antiAlias) const { | 72 bool antiAlias) const { |
| 72 | 73 |
| 73 // TODO: Support inverse fill | 74 // TODO: Support inverse fill |
| 74 // TODO: Support strokes | 75 // TODO: Support strokes |
| 75 if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInver
seFillType() | 76 if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInver
seFillType() |
| 76 || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) { | 77 || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) { |
| 77 return false; | 78 return false; |
| 78 } | 79 } |
| 79 | 80 |
| 80 // currently don't support perspective | 81 // currently don't support perspective |
| 81 const GrDrawState& drawState = target->getDrawState(); | 82 const SkMatrix& vm = drawState->getViewMatrix(); |
| 82 const SkMatrix& vm = drawState.getViewMatrix(); | |
| 83 if (vm.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 = vm.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 GrAADistanceFieldPathRenderer::onGetStencilSuppor
t( | 96 GrPathRenderer::StencilSupport |
| 97 const SkP
ath&, | 97 GrAADistanceFieldPathRenderer::onGetStencilSupport(const GrDrawTarget*, |
| 98 const SkS
trokeRec&, | 98 const GrDrawState*, |
| 99 const GrD
rawTarget*) const { | 99 const SkPath&, |
| 100 const SkStrokeRec&) const { |
| 100 return GrPathRenderer::kNoSupport_StencilSupport; | 101 return GrPathRenderer::kNoSupport_StencilSupport; |
| 101 } | 102 } |
| 102 | 103 |
| 103 //////////////////////////////////////////////////////////////////////////////// | 104 //////////////////////////////////////////////////////////////////////////////// |
| 104 | 105 |
| 105 // position + texture coord | 106 // position + texture coord |
| 106 extern const GrVertexAttrib gSDFPathVertexAttribs[] = { | 107 extern const GrVertexAttrib gSDFPathVertexAttribs[] = { |
| 107 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, | 108 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, |
| 108 { kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAtt
ribBinding } | 109 { kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAtt
ribBinding } |
| 109 }; | 110 }; |
| 110 static const size_t kSDFPathVASize = 2 * sizeof(SkPoint); | 111 static const size_t kSDFPathVASize = 2 * sizeof(SkPoint); |
| 111 | 112 |
| 112 bool GrAADistanceFieldPathRenderer::onDrawPath(const SkPath& path, | 113 bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target, |
| 114 GrDrawState* drawState, |
| 115 const SkPath& path, |
| 113 const SkStrokeRec& stroke, | 116 const SkStrokeRec& stroke, |
| 114 GrDrawTarget* target, | |
| 115 bool antiAlias) { | 117 bool antiAlias) { |
| 116 // we've already bailed on inverse filled paths, so this is safe | 118 // we've already bailed on inverse filled paths, so this is safe |
| 117 if (path.isEmpty()) { | 119 if (path.isEmpty()) { |
| 118 return true; | 120 return true; |
| 119 } | 121 } |
| 120 | 122 |
| 121 SkASSERT(fContext); | 123 SkASSERT(fContext); |
| 122 | 124 |
| 123 // get mip level | 125 // get mip level |
| 124 const GrDrawState& drawState = target->getDrawState(); | 126 const SkMatrix& vm = drawState->getViewMatrix(); |
| 125 const SkMatrix& vm = drawState.getViewMatrix(); | |
| 126 SkScalar maxScale = vm.getMaxScale(); | 127 SkScalar maxScale = vm.getMaxScale(); |
| 127 const SkRect& bounds = path.getBounds(); | 128 const SkRect& bounds = path.getBounds(); |
| 128 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); | 129 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); |
| 129 SkScalar size = maxScale*maxDim; | 130 SkScalar size = maxScale*maxDim; |
| 130 uint32_t desiredDimension; | 131 uint32_t desiredDimension; |
| 131 if (size <= kSmallMIP) { | 132 if (size <= kSmallMIP) { |
| 132 desiredDimension = kSmallMIP; | 133 desiredDimension = kSmallMIP; |
| 133 } else if (size <= kMediumMIP) { | 134 } else if (size <= kMediumMIP) { |
| 134 desiredDimension = kMediumMIP; | 135 desiredDimension = kMediumMIP; |
| 135 } else { | 136 } else { |
| 136 desiredDimension = kLargeMIP; | 137 desiredDimension = kLargeMIP; |
| 137 } | 138 } |
| 138 | 139 |
| 139 // check to see if path is cached | 140 // check to see if path is cached |
| 140 // TODO: handle stroked vs. filled version of same path | 141 // TODO: handle stroked vs. filled version of same path |
| 141 PathData::Key key = { path.getGenerationID(), desiredDimension }; | 142 PathData::Key key = { path.getGenerationID(), desiredDimension }; |
| 142 PathData* pathData = fPathCache.find(key); | 143 PathData* pathData = fPathCache.find(key); |
| 143 if (NULL == pathData) { | 144 if (NULL == pathData) { |
| 144 SkScalar scale = desiredDimension/maxDim; | 145 SkScalar scale = desiredDimension/maxDim; |
| 145 pathData = this->addPathToAtlas(path, stroke, antiAlias, desiredDimensio
n, scale); | 146 pathData = this->addPathToAtlas(path, stroke, antiAlias, desiredDimensio
n, scale); |
| 146 if (NULL == pathData) { | 147 if (NULL == pathData) { |
| 147 return false; | 148 return false; |
| 148 } | 149 } |
| 149 } | 150 } |
| 150 | 151 |
| 151 // use signed distance field to render | 152 // use signed distance field to render |
| 152 return this->internalDrawPath(path, pathData, target); | 153 return this->internalDrawPath(target, drawState, path, pathData); |
| 153 } | 154 } |
| 154 | 155 |
| 155 // padding around path bounds to allow for antialiased pixels | 156 // padding around path bounds to allow for antialiased pixels |
| 156 const SkScalar kAntiAliasPad = 1.0f; | 157 const SkScalar kAntiAliasPad = 1.0f; |
| 157 | 158 |
| 158 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
oAtlas( | 159 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT
oAtlas( |
| 159 const Sk
Path& path, | 160 const Sk
Path& path, |
| 160 const Sk
StrokeRec& stroke, | 161 const Sk
StrokeRec& stroke, |
| 161 bool ant
iAlias, | 162 bool ant
iAlias, |
| 162 uint32_t
dimension, | 163 uint32_t
dimension, |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 #endif | 304 #endif |
| 304 } | 305 } |
| 305 } | 306 } |
| 306 | 307 |
| 307 // tell the atlas to free the plot | 308 // tell the atlas to free the plot |
| 308 GrAtlas::RemovePlot(&fPlotUsage, plot); | 309 GrAtlas::RemovePlot(&fPlotUsage, plot); |
| 309 | 310 |
| 310 return true; | 311 return true; |
| 311 } | 312 } |
| 312 | 313 |
| 313 bool GrAADistanceFieldPathRenderer::internalDrawPath(const SkPath& path, | 314 bool GrAADistanceFieldPathRenderer::internalDrawPath(GrDrawTarget* target, |
| 314 const PathData* pathData, | 315 GrDrawState* drawState, |
| 315 GrDrawTarget* target) { | 316 const SkPath& path, |
| 317 const PathData* pathData) { |
| 316 GrTexture* texture = fAtlas->getTexture(); | 318 GrTexture* texture = fAtlas->getTexture(); |
| 317 GrDrawState* drawState = target->drawState(); | |
| 318 GrDrawState::AutoRestoreEffects are(drawState); | 319 GrDrawState::AutoRestoreEffects are(drawState); |
| 319 | 320 |
| 320 SkASSERT(pathData->fPlot); | 321 SkASSERT(pathData->fPlot); |
| 321 GrDrawTarget::DrawToken drawToken = target->getCurrentDrawToken(); | 322 GrDrawTarget::DrawToken drawToken = target->getCurrentDrawToken(); |
| 322 pathData->fPlot->setDrawToken(drawToken); | 323 pathData->fPlot->setDrawToken(drawToken); |
| 323 | 324 |
| 324 // make me some vertices | 325 // make me some vertices |
| 325 drawState->setVertexAttribs<gSDFPathVertexAttribs>(SK_ARRAY_COUNT(gSDFPathVe
rtexAttribs), | 326 drawState->setVertexAttribs<gSDFPathVertexAttribs>(SK_ARRAY_COUNT(gSDFPathVe
rtexAttribs), |
| 326 kSDFPathVASize); | 327 kSDFPathVASize); |
| 327 void* vertices = NULL; | 328 void* vertices = NULL; |
| 328 bool success = target->reserveVertexAndIndexSpace(4, 0, &vertices, NULL); | 329 bool success = target->reserveVertexAndIndexSpace(4, drawState->getVertexStr
ide(), 0, &vertices, |
| 330 NULL); |
| 329 GrAlwaysAssert(success); | 331 GrAlwaysAssert(success); |
| 330 | 332 |
| 331 SkScalar dx = pathData->fBounds.fLeft; | 333 SkScalar dx = pathData->fBounds.fLeft; |
| 332 SkScalar dy = pathData->fBounds.fTop; | 334 SkScalar dy = pathData->fBounds.fTop; |
| 333 SkScalar width = pathData->fBounds.width(); | 335 SkScalar width = pathData->fBounds.width(); |
| 334 SkScalar height = pathData->fBounds.height(); | 336 SkScalar height = pathData->fBounds.height(); |
| 335 | 337 |
| 336 SkScalar invScale = 1.0f/pathData->fScale; | 338 SkScalar invScale = 1.0f/pathData->fScale; |
| 337 dx *= invScale; | 339 dx *= invScale; |
| 338 dy *= invScale; | 340 dy *= invScale; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 368 if (flags != fEffectFlags) { | 370 if (flags != fEffectFlags) { |
| 369 fCachedGeometryProcessor.reset(GrDistanceFieldNoGammaTextureEffect::Crea
te(texture, | 371 fCachedGeometryProcessor.reset(GrDistanceFieldNoGammaTextureEffect::Crea
te(texture, |
| 370
params, | 372
params, |
| 371
flags)); | 373
flags)); |
| 372 fEffectFlags = flags; | 374 fEffectFlags = flags; |
| 373 } | 375 } |
| 374 drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); | 376 drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); |
| 375 | 377 |
| 376 vm.mapRect(&r); | 378 vm.mapRect(&r); |
| 377 target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 379 target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |
| 378 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r); | 380 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6,
&r); |
| 379 target->resetVertexSource(); | 381 target->resetVertexSource(); |
| 380 | 382 |
| 381 return true; | 383 return true; |
| 382 } | 384 } |
| 383 | 385 |
| OLD | NEW |