| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2014 Google Inc. | 3 * Copyright 2014 Google Inc. |
| 4 * Copyright 2016 ARM Ltd. | |
| 5 * | 4 * |
| 6 * 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 |
| 7 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 8 */ | 7 */ |
| 9 | 8 |
| 10 #include "GrAADistanceFieldPathRenderer.h" | 9 #include "GrAADistanceFieldPathRenderer.h" |
| 11 | 10 |
| 12 #include "GrBatchFlushState.h" | 11 #include "GrBatchFlushState.h" |
| 13 #include "GrBatchTest.h" | 12 #include "GrBatchTest.h" |
| 14 #include "GrContext.h" | 13 #include "GrContext.h" |
| 15 #include "GrPipelineBuilder.h" | 14 #include "GrPipelineBuilder.h" |
| 16 #include "GrResourceProvider.h" | 15 #include "GrResourceProvider.h" |
| 17 #include "GrSurfacePriv.h" | 16 #include "GrSurfacePriv.h" |
| 18 #include "GrSWMaskHelper.h" | 17 #include "GrSWMaskHelper.h" |
| 19 #include "GrTexturePriv.h" | 18 #include "GrTexturePriv.h" |
| 20 #include "GrVertexBuffer.h" | 19 #include "GrVertexBuffer.h" |
| 21 #include "batches/GrVertexBatch.h" | 20 #include "batches/GrVertexBatch.h" |
| 22 #include "effects/GrDistanceFieldGeoProc.h" | 21 #include "effects/GrDistanceFieldGeoProc.h" |
| 23 | 22 |
| 24 #include "SkDistanceFieldGen.h" | 23 #include "SkDistanceFieldGen.h" |
| 25 #include "GrDistanceFieldGenFromVector.h" | |
| 26 #include "SkRTConf.h" | 24 #include "SkRTConf.h" |
| 27 | 25 |
| 28 #define ATLAS_TEXTURE_WIDTH 2048 | 26 #define ATLAS_TEXTURE_WIDTH 2048 |
| 29 #define ATLAS_TEXTURE_HEIGHT 2048 | 27 #define ATLAS_TEXTURE_HEIGHT 2048 |
| 30 #define PLOT_WIDTH 512 | 28 #define PLOT_WIDTH 512 |
| 31 #define PLOT_HEIGHT 256 | 29 #define PLOT_HEIGHT 256 |
| 32 | 30 |
| 33 #define NUM_PLOTS_X (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH) | 31 #define NUM_PLOTS_X (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH) |
| 34 #define NUM_PLOTS_Y (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT) | 32 #define NUM_PLOTS_Y (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT) |
| 35 | 33 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 if (!args.fShaderCaps->shaderDerivativeSupport() || !args.fAntiAlias || | 87 if (!args.fShaderCaps->shaderDerivativeSupport() || !args.fAntiAlias || |
| 90 SkStrokeRec::kHairline_Style == args.fStroke->getStyle() || | 88 SkStrokeRec::kHairline_Style == args.fStroke->getStyle() || |
| 91 args.fPath->isInverseFillType() || args.fPath->isVolatile()) { | 89 args.fPath->isInverseFillType() || args.fPath->isVolatile()) { |
| 92 return false; | 90 return false; |
| 93 } | 91 } |
| 94 | 92 |
| 95 // currently don't support perspective | 93 // currently don't support perspective |
| 96 if (args.fViewMatrix->hasPerspective()) { | 94 if (args.fViewMatrix->hasPerspective()) { |
| 97 return false; | 95 return false; |
| 98 } | 96 } |
| 99 | 97 |
| 100 // only support paths with bounds within kMediumMIP by kMediumMIP, | 98 // only support paths with bounds within kMediumMIP by kMediumMIP, |
| 101 // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP | 99 // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP |
| 102 // the goal is to accelerate rendering of lots of small paths that may be sc
aling | 100 // the goal is to accelerate rendering of lots of small paths that may be sc
aling |
| 103 SkScalar maxScale = args.fViewMatrix->getMaxScale(); | 101 SkScalar maxScale = args.fViewMatrix->getMaxScale(); |
| 104 const SkRect& bounds = args.fPath->getBounds(); | 102 const SkRect& bounds = args.fPath->getBounds(); |
| 105 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); | 103 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); |
| 106 // Approximate stroked size by adding the maximum of the stroke width or 2x
the miter limit | 104 // Approximate stroked size by adding the maximum of the stroke width or 2x
the miter limit |
| 107 if (!args.fStroke->isFillStyle()) { | 105 if (!args.fStroke->isFillStyle()) { |
| 108 SkScalar extraWidth = args.fStroke->getWidth(); | 106 SkScalar extraWidth = args.fStroke->getWidth(); |
| 109 if (SkPaint::kMiter_Join == args.fStroke->getJoin()) { | 107 if (SkPaint::kMiter_Join == args.fStroke->getJoin()) { |
| 110 extraWidth = SkTMax(extraWidth, 2.0f*args.fStroke->getMiter()); | 108 extraWidth = SkTMax(extraWidth, 2.0f*args.fStroke->getMiter()); |
| 111 } | 109 } |
| 112 maxDim += extraWidth; | 110 maxDim += extraWidth; |
| 113 } | 111 } |
| 114 | 112 |
| 115 return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP; | 113 return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP; |
| 116 } | 114 } |
| 117 | 115 |
| 118 //////////////////////////////////////////////////////////////////////////////// | 116 //////////////////////////////////////////////////////////////////////////////// |
| 119 | 117 |
| 120 // padding around path bounds to allow for antialiased pixels | 118 // padding around path bounds to allow for antialiased pixels |
| 121 static const SkScalar kAntiAliasPad = 1.0f; | 119 static const SkScalar kAntiAliasPad = 1.0f; |
| 122 | 120 |
| 123 class AADistanceFieldPathBatch : public GrVertexBatch { | 121 class AADistanceFieldPathBatch : public GrVertexBatch { |
| 124 public: | 122 public: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 148 bool fAntiAlias; | 146 bool fAntiAlias; |
| 149 }; | 147 }; |
| 150 | 148 |
| 151 static GrDrawBatch* Create(const Geometry& geometry, const SkMatrix& viewMat
rix, | 149 static GrDrawBatch* Create(const Geometry& geometry, const SkMatrix& viewMat
rix, |
| 152 GrBatchAtlas* atlas, PathCache* pathCache, PathDa
taList* pathList) { | 150 GrBatchAtlas* atlas, PathCache* pathCache, PathDa
taList* pathList) { |
| 153 return new AADistanceFieldPathBatch(geometry, viewMatrix, atlas, pathCac
he, pathList); | 151 return new AADistanceFieldPathBatch(geometry, viewMatrix, atlas, pathCac
he, pathList); |
| 154 } | 152 } |
| 155 | 153 |
| 156 const char* name() const override { return "AADistanceFieldPathBatch"; } | 154 const char* name() const override { return "AADistanceFieldPathBatch"; } |
| 157 | 155 |
| 158 void computePipelineOptimizations(GrInitInvariantOutput* color, | 156 void computePipelineOptimizations(GrInitInvariantOutput* color, |
| 159 GrInitInvariantOutput* coverage, | 157 GrInitInvariantOutput* coverage, |
| 160 GrBatchToXPOverrides* overrides) const ove
rride { | 158 GrBatchToXPOverrides* overrides) const ove
rride { |
| 161 color->setKnownFourComponents(fGeoData[0].fColor); | 159 color->setKnownFourComponents(fGeoData[0].fColor); |
| 162 coverage->setUnknownSingleComponent(); | 160 coverage->setUnknownSingleComponent(); |
| 163 } | 161 } |
| 164 | 162 |
| 165 private: | 163 private: |
| 166 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 164 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
| 167 // Handle any color overrides | 165 // Handle any color overrides |
| 168 if (!overrides.readsColor()) { | 166 if (!overrides.readsColor()) { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 devPathBounds.fRight = intPad + width; | 350 devPathBounds.fRight = intPad + width; |
| 353 devPathBounds.fBottom = intPad + height; | 351 devPathBounds.fBottom = intPad + height; |
| 354 devPathBounds.outset(intPad, intPad); | 352 devPathBounds.outset(intPad, intPad); |
| 355 | 353 |
| 356 // draw path to bitmap | 354 // draw path to bitmap |
| 357 SkMatrix drawMatrix; | 355 SkMatrix drawMatrix; |
| 358 drawMatrix.setTranslate(-bounds.left(), -bounds.top()); | 356 drawMatrix.setTranslate(-bounds.left(), -bounds.top()); |
| 359 drawMatrix.postScale(scale, scale); | 357 drawMatrix.postScale(scale, scale); |
| 360 drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad); | 358 drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad); |
| 361 | 359 |
| 360 // setup bitmap backing |
| 362 SkASSERT(devPathBounds.fLeft == 0); | 361 SkASSERT(devPathBounds.fLeft == 0); |
| 363 SkASSERT(devPathBounds.fTop == 0); | 362 SkASSERT(devPathBounds.fTop == 0); |
| 363 SkAutoPixmapStorage dst; |
| 364 if (!dst.tryAlloc(SkImageInfo::MakeA8(devPathBounds.width(), |
| 365 devPathBounds.height()))) { |
| 366 return false; |
| 367 } |
| 368 sk_bzero(dst.writable_addr(), dst.getSafeSize()); |
| 364 | 369 |
| 365 // setup signed distance field storage | 370 // rasterize path |
| 366 SkIRect sdfPathBounds = devPathBounds.makeOutset(SK_DistanceFieldPad, SK
_DistanceFieldPad); | 371 SkPaint paint; |
| 367 width = sdfPathBounds.width(); | 372 paint.setStyle(SkPaint::kFill_Style); |
| 368 height = sdfPathBounds.height(); | 373 paint.setAntiAlias(antiAlias); |
| 374 |
| 375 SkDraw draw; |
| 376 sk_bzero(&draw, sizeof(draw)); |
| 377 |
| 378 SkRasterClip rasterClip; |
| 379 rasterClip.setRect(devPathBounds); |
| 380 draw.fRC = &rasterClip; |
| 381 draw.fClip = &rasterClip.bwRgn(); |
| 382 draw.fMatrix = &drawMatrix; |
| 383 draw.fDst = dst; |
| 384 |
| 385 draw.drawPathCoverage(path, paint); |
| 386 |
| 387 // generate signed distance field |
| 388 devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad); |
| 389 width = devPathBounds.width(); |
| 390 height = devPathBounds.height(); |
| 369 // TODO We should really generate this directly into the plot somehow | 391 // TODO We should really generate this directly into the plot somehow |
| 370 SkAutoSMalloc<1024> dfStorage(width * height * sizeof(unsigned char)); | 392 SkAutoSMalloc<1024> dfStorage(width * height * sizeof(unsigned char)); |
| 371 | 393 |
| 372 // Generate signed distance field directly from SkPath | 394 // Generate signed distance field |
| 373 GrGenerateDistanceFieldFromPath((unsigned char*)dfStorage.get(), | 395 SkGenerateDistanceFieldFromA8Image((unsigned char*)dfStorage.get(), |
| 374 path, drawMatrix, | 396 (const unsigned char*)dst.addr(), |
| 375 width, height, width * sizeof(unsigned c
har)); | 397 dst.width(), dst.height(), dst.rowByt
es()); |
| 376 | 398 |
| 377 // add to atlas | 399 // add to atlas |
| 378 SkIPoint16 atlasLocation; | 400 SkIPoint16 atlasLocation; |
| 379 GrBatchAtlas::AtlasID id; | 401 GrBatchAtlas::AtlasID id; |
| 380 bool success = atlas->addToAtlas(&id, target, width, height, dfStorage.g
et(), | 402 bool success = atlas->addToAtlas(&id, target, width, height, dfStorage.g
et(), |
| 381 &atlasLocation); | 403 &atlasLocation); |
| 382 if (!success) { | 404 if (!success) { |
| 383 this->flush(target, flushInfo); | 405 this->flush(target, flushInfo); |
| 384 target->initDraw(dfProcessor, pipeline); | 406 target->initDraw(dfProcessor, pipeline); |
| 385 | 407 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 geometry.fPath = *args.fPath; | 558 geometry.fPath = *args.fPath; |
| 537 } else { | 559 } else { |
| 538 args.fStroke->applyToPath(&geometry.fPath, *args.fPath); | 560 args.fStroke->applyToPath(&geometry.fPath, *args.fPath); |
| 539 } | 561 } |
| 540 geometry.fColor = args.fColor; | 562 geometry.fColor = args.fColor; |
| 541 geometry.fAntiAlias = args.fAntiAlias; | 563 geometry.fAntiAlias = args.fAntiAlias; |
| 542 // Note: this is the generation ID of the _original_ path. When a new path i
s | 564 // Note: this is the generation ID of the _original_ path. When a new path i
s |
| 543 // generated due to stroking it is important that the original path's id is
used | 565 // generated due to stroking it is important that the original path's id is
used |
| 544 // for caching. | 566 // for caching. |
| 545 geometry.fGenID = args.fPath->getGenerationID(); | 567 geometry.fGenID = args.fPath->getGenerationID(); |
| 546 | 568 |
| 547 SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry, | 569 SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry, |
| 548 *args.fView
Matrix, fAtlas, | 570 *args.fView
Matrix, fAtlas, |
| 549 &fPathCache
, &fPathList)); | 571 &fPathCache
, &fPathList)); |
| 550 args.fTarget->drawBatch(*args.fPipelineBuilder, batch); | 572 args.fTarget->drawBatch(*args.fPipelineBuilder, batch); |
| 551 | 573 |
| 552 return true; | 574 return true; |
| 553 } | 575 } |
| 554 | 576 |
| 555 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 577 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 556 | 578 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 geometry.fAntiAlias = random->nextBool(); | 643 geometry.fAntiAlias = random->nextBool(); |
| 622 geometry.fGenID = random->nextU(); | 644 geometry.fGenID = random->nextU(); |
| 623 | 645 |
| 624 return AADistanceFieldPathBatch::Create(geometry, viewMatrix, | 646 return AADistanceFieldPathBatch::Create(geometry, viewMatrix, |
| 625 gTestStruct.fAtlas, | 647 gTestStruct.fAtlas, |
| 626 &gTestStruct.fPathCache, | 648 &gTestStruct.fPathCache, |
| 627 &gTestStruct.fPathList); | 649 &gTestStruct.fPathList); |
| 628 } | 650 } |
| 629 | 651 |
| 630 #endif | 652 #endif |
| OLD | NEW |