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 |