OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 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 "GrAALinearizingConvexPathRenderer.h" | 9 #include "GrAALinearizingConvexPathRenderer.h" |
10 | 10 |
11 #include "GrAAConvexTessellator.h" | 11 #include "GrAAConvexTessellator.h" |
12 #include "GrBatch.h" | 12 #include "GrBatch.h" |
13 #include "GrBatchTarget.h" | 13 #include "GrBatchTarget.h" |
14 #include "GrBatchTest.h" | 14 #include "GrBatchTest.h" |
15 #include "GrContext.h" | 15 #include "GrContext.h" |
16 #include "GrDefaultGeoProcFactory.h" | 16 #include "GrDefaultGeoProcFactory.h" |
17 #include "GrGeometryProcessor.h" | 17 #include "GrGeometryProcessor.h" |
18 #include "GrInvariantOutput.h" | 18 #include "GrInvariantOutput.h" |
19 #include "GrPathUtils.h" | 19 #include "GrPathUtils.h" |
20 #include "GrProcessor.h" | 20 #include "GrProcessor.h" |
21 #include "GrPipelineBuilder.h" | 21 #include "GrPipelineBuilder.h" |
22 #include "GrStrokeInfo.h" | 22 #include "GrStrokeInfo.h" |
23 #include "SkGeometry.h" | 23 #include "SkGeometry.h" |
24 #include "SkString.h" | 24 #include "SkString.h" |
25 #include "SkTraceEvent.h" | 25 #include "SkTraceEvent.h" |
| 26 #include "SkPathPriv.h" |
26 #include "gl/GrGLProcessor.h" | 27 #include "gl/GrGLProcessor.h" |
27 #include "gl/GrGLGeometryProcessor.h" | 28 #include "gl/GrGLGeometryProcessor.h" |
28 #include "gl/builders/GrGLProgramBuilder.h" | 29 #include "gl/builders/GrGLProgramBuilder.h" |
29 | 30 |
30 #define DEFAULT_BUFFER_SIZE 100 | 31 static const int DEFAULT_BUFFER_SIZE = 100; |
| 32 |
| 33 // The thicker the stroke, the harder it is to produce high-quality results usin
g tessellation. For |
| 34 // the time being, we simply drop back to software rendering above this stroke w
idth. |
| 35 static const SkScalar kMaxStrokeWidth = 20.0; |
31 | 36 |
32 GrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() { | 37 GrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() { |
33 } | 38 } |
34 | 39 |
35 /////////////////////////////////////////////////////////////////////////////// | 40 /////////////////////////////////////////////////////////////////////////////// |
36 | 41 |
37 bool GrAALinearizingConvexPathRenderer::canDrawPath(const GrDrawTarget* target, | 42 bool GrAALinearizingConvexPathRenderer::canDrawPath(const GrDrawTarget* target, |
38 const GrPipelineBuilder*, | 43 const GrPipelineBuilder*, |
39 const SkMatrix& viewMatrix, | 44 const SkMatrix& viewMatrix, |
40 const SkPath& path, | 45 const SkPath& path, |
41 const GrStrokeInfo& stroke, | 46 const GrStrokeInfo& stroke, |
42 bool antiAlias) const { | 47 bool antiAlias) const { |
43 return (antiAlias && stroke.isFillStyle() && !path.isInverseFillType() && pa
th.isConvex()); | 48 if (!antiAlias) { |
| 49 return false; |
| 50 } |
| 51 if (path.isInverseFillType()) { |
| 52 return false; |
| 53 } |
| 54 if (!path.isConvex()) { |
| 55 return false; |
| 56 } |
| 57 if (stroke.getStyle() == SkStrokeRec::kStroke_Style) { |
| 58 return viewMatrix.isSimilarity() && stroke.getWidth() >= 1.0f && |
| 59 stroke.getWidth() <= kMaxStrokeWidth && !stroke.isDashed() && |
| 60 SkPathPriv::LastVerbIsClose(path) && stroke.getJoin() != SkPaint
::Join::kRound_Join; |
| 61 } |
| 62 return stroke.getStyle() == SkStrokeRec::kFill_Style; |
44 } | 63 } |
45 | 64 |
46 // extract the result vertices and indices from the GrAAConvexTessellator | 65 // extract the result vertices and indices from the GrAAConvexTessellator |
47 static void extract_verts(const GrAAConvexTessellator& tess, | 66 static void extract_verts(const GrAAConvexTessellator& tess, |
48 void* vertices, | 67 void* vertices, |
49 size_t vertexStride, | 68 size_t vertexStride, |
50 GrColor color, | 69 GrColor color, |
51 uint16_t firstIndex, | 70 uint16_t firstIndex, |
52 uint16_t* idxs, | 71 uint16_t* idxs, |
53 bool tweakAlphaForCoverage) { | 72 bool tweakAlphaForCoverage) { |
54 intptr_t verts = reinterpret_cast<intptr_t>(vertices); | 73 intptr_t verts = reinterpret_cast<intptr_t>(vertices); |
55 | 74 |
56 for (int i = 0; i < tess.numPts(); ++i) { | 75 for (int i = 0; i < tess.numPts(); ++i) { |
57 *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i); | 76 *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i); |
58 } | 77 } |
59 | 78 |
60 // Make 'verts' point to the colors | 79 // Make 'verts' point to the colors |
61 verts += sizeof(SkPoint); | 80 verts += sizeof(SkPoint); |
62 for (int i = 0; i < tess.numPts(); ++i) { | 81 for (int i = 0; i < tess.numPts(); ++i) { |
63 SkASSERT(tess.depth(i) >= -0.5f && tess.depth(i) <= 0.5f); | |
64 if (tweakAlphaForCoverage) { | 82 if (tweakAlphaForCoverage) { |
65 SkASSERT(SkScalarRoundToInt(255.0f * (tess.depth(i) + 0.5f)) <= 255)
; | 83 SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255); |
66 unsigned scale = SkScalarRoundToInt(255.0f * (tess.depth(i) + 0.5f))
; | 84 unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i)); |
67 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, s
cale); | 85 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, s
cale); |
68 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; | 86 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; |
69 } else { | 87 } else { |
70 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 88 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
71 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)
) = | 89 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)
) = |
72 tess.depth(i
) + 0.5f; | 90 tess.coverage(i); |
73 } | 91 } |
74 } | 92 } |
75 | 93 |
76 for (int i = 0; i < tess.numIndices(); ++i) { | 94 for (int i = 0; i < tess.numIndices(); ++i) { |
77 idxs[i] = tess.index(i) + firstIndex; | 95 idxs[i] = tess.index(i) + firstIndex; |
78 } | 96 } |
79 } | 97 } |
80 | 98 |
81 static const GrGeometryProcessor* create_fill_gp(bool tweakAlphaForCoverage, | 99 static const GrGeometryProcessor* create_fill_gp(bool tweakAlphaForCoverage, |
82 const SkMatrix& localMatrix, | 100 const SkMatrix& localMatrix, |
83 bool usesLocalCoords, | 101 bool usesLocalCoords, |
84 bool coverageIgnored) { | 102 bool coverageIgnored) { |
85 uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType; | 103 uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType; |
86 if (!tweakAlphaForCoverage) { | 104 if (!tweakAlphaForCoverage) { |
87 flags |= GrDefaultGeoProcFactory::kCoverage_GPType; | 105 flags |= GrDefaultGeoProcFactory::kCoverage_GPType; |
88 } | 106 } |
89 | 107 |
90 return GrDefaultGeoProcFactory::Create(flags, GrColor_WHITE, usesLocalCoords
, coverageIgnored, | 108 return GrDefaultGeoProcFactory::Create(flags, GrColor_WHITE, usesLocalCoords
, coverageIgnored, |
91 SkMatrix::I(), localMatrix); | 109 SkMatrix::I(), localMatrix); |
92 } | 110 } |
93 | 111 |
94 class AAFlatteningConvexPathBatch : public GrBatch { | 112 class AAFlatteningConvexPathBatch : public GrBatch { |
95 public: | 113 public: |
96 struct Geometry { | 114 struct Geometry { |
97 GrColor fColor; | 115 GrColor fColor; |
98 SkMatrix fViewMatrix; | 116 SkMatrix fViewMatrix; |
99 SkPath fPath; | 117 SkPath fPath; |
| 118 SkScalar fStrokeWidth; |
| 119 SkPaint::Join fJoin; |
| 120 SkScalar fMiterLimit; |
100 }; | 121 }; |
101 | 122 |
102 static GrBatch* Create(const Geometry& geometry) { | 123 static GrBatch* Create(const Geometry& geometry) { |
103 return SkNEW_ARGS(AAFlatteningConvexPathBatch, (geometry)); | 124 return SkNEW_ARGS(AAFlatteningConvexPathBatch, (geometry)); |
104 } | 125 } |
105 | 126 |
106 const char* name() const override { return "AAConvexBatch"; } | 127 const char* name() const override { return "AAConvexBatch"; } |
107 | 128 |
108 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 129 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
109 // When this is called on a batch, there is only one geometry bundle | 130 // When this is called on a batch, there is only one geometry bundle |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 uint16_t* idxs = batchTarget->makeIndexSpace(indexCount, &indexBuffer, &
firstIndex); | 172 uint16_t* idxs = batchTarget->makeIndexSpace(indexCount, &indexBuffer, &
firstIndex); |
152 if (!idxs) { | 173 if (!idxs) { |
153 SkDebugf("Could not allocate indices\n"); | 174 SkDebugf("Could not allocate indices\n"); |
154 return; | 175 return; |
155 } | 176 } |
156 memcpy(idxs, indices, indexCount * sizeof(uint16_t)); | 177 memcpy(idxs, indices, indexCount * sizeof(uint16_t)); |
157 info.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer,
firstVertex, | 178 info.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer,
firstVertex, |
158 firstIndex, vertexCount, indexCount); | 179 firstIndex, vertexCount, indexCount); |
159 batchTarget->draw(info); | 180 batchTarget->draw(info); |
160 } | 181 } |
161 | 182 |
162 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) override { | 183 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) override { |
163 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); | 184 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); |
164 | 185 |
165 SkMatrix invert; | 186 SkMatrix invert; |
166 if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) { | 187 if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) { |
167 SkDebugf("Could not invert viewmatrix\n"); | 188 SkDebugf("Could not invert viewmatrix\n"); |
168 return; | 189 return; |
169 } | 190 } |
170 | 191 |
171 // Setup GrGeometryProcessor | 192 // Setup GrGeometryProcessor |
172 SkAutoTUnref<const GrGeometryProcessor> gp( | 193 SkAutoTUnref<const GrGeometryProcessor> gp( |
173 create_fill_gp(canTweakAlphaForC
overage, invert, | 194 create_fill_gp(canTweakAlphaForC
overage, invert, |
174 this->usesLocalCo
ords(), | 195 this->usesLocalCo
ords(), |
175 this->coverageIgn
ored())); | 196 this->coverageIgn
ored())); |
176 | 197 |
177 batchTarget->initDraw(gp, pipeline); | 198 batchTarget->initDraw(gp, pipeline); |
178 | 199 |
179 size_t vertexStride = gp->getVertexStride(); | 200 size_t vertexStride = gp->getVertexStride(); |
180 | 201 |
181 SkASSERT(canTweakAlphaForCoverage ? | 202 SkASSERT(canTweakAlphaForCoverage ? |
182 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt
tr) : | 203 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt
tr) : |
183 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo
verageAttr)); | 204 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo
verageAttr)); |
184 | 205 |
185 GrAAConvexTessellator tess; | |
186 | |
187 int instanceCount = fGeoData.count(); | 206 int instanceCount = fGeoData.count(); |
188 | 207 |
189 int vertexCount = 0; | 208 int vertexCount = 0; |
190 int indexCount = 0; | 209 int indexCount = 0; |
191 int maxVertices = DEFAULT_BUFFER_SIZE; | 210 int maxVertices = DEFAULT_BUFFER_SIZE; |
192 int maxIndices = DEFAULT_BUFFER_SIZE; | 211 int maxIndices = DEFAULT_BUFFER_SIZE; |
193 uint8_t* vertices = (uint8_t*) malloc(maxVertices * vertexStride); | 212 uint8_t* vertices = (uint8_t*) malloc(maxVertices * vertexStride); |
194 uint16_t* indices = (uint16_t*) malloc(maxIndices * sizeof(uint16_t)); | 213 uint16_t* indices = (uint16_t*) malloc(maxIndices * sizeof(uint16_t)); |
195 for (int i = 0; i < instanceCount; i++) { | 214 for (int i = 0; i < instanceCount; i++) { |
196 tess.rewind(); | |
197 | |
198 Geometry& args = fGeoData[i]; | 215 Geometry& args = fGeoData[i]; |
| 216 GrAAConvexTessellator tess(args.fStrokeWidth, args.fJoin, args.fMite
rLimit); |
199 | 217 |
200 if (!tess.tessellate(args.fViewMatrix, args.fPath)) { | 218 if (!tess.tessellate(args.fViewMatrix, args.fPath)) { |
201 continue; | 219 continue; |
202 } | 220 } |
203 | 221 |
204 int currentIndices = tess.numIndices(); | 222 int currentIndices = tess.numIndices(); |
205 SkASSERT(currentIndices <= UINT16_MAX); | 223 SkASSERT(currentIndices <= UINT16_MAX); |
206 if (indexCount + currentIndices > UINT16_MAX) { | 224 if (indexCount + currentIndices > UINT16_MAX) { |
207 // if we added the current instance, we would overflow the indic
es we can store in a | 225 // if we added the current instance, we would overflow the indic
es we can store in a |
208 // uint16_t. Draw what we've got so far and reset. | 226 // uint16_t. Draw what we've got so far and reset. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 298 |
281 BatchTracker fBatch; | 299 BatchTracker fBatch; |
282 SkSTArray<1, Geometry, true> fGeoData; | 300 SkSTArray<1, Geometry, true> fGeoData; |
283 }; | 301 }; |
284 | 302 |
285 bool GrAALinearizingConvexPathRenderer::onDrawPath(GrDrawTarget* target, | 303 bool GrAALinearizingConvexPathRenderer::onDrawPath(GrDrawTarget* target, |
286 GrPipelineBuilder* pipelineBu
ilder, | 304 GrPipelineBuilder* pipelineBu
ilder, |
287 GrColor color, | 305 GrColor color, |
288 const SkMatrix& vm, | 306 const SkMatrix& vm, |
289 const SkPath& path, | 307 const SkPath& path, |
290 const GrStrokeInfo&, | 308 const GrStrokeInfo& stroke, |
291 bool antiAlias) { | 309 bool antiAlias) { |
292 if (path.isEmpty()) { | 310 if (path.isEmpty()) { |
293 return true; | 311 return true; |
294 } | 312 } |
295 AAFlatteningConvexPathBatch::Geometry geometry; | 313 AAFlatteningConvexPathBatch::Geometry geometry; |
296 geometry.fColor = color; | 314 geometry.fColor = color; |
297 geometry.fViewMatrix = vm; | 315 geometry.fViewMatrix = vm; |
298 geometry.fPath = path; | 316 geometry.fPath = path; |
| 317 geometry.fStrokeWidth = stroke.isFillStyle() ? -1.0f : stroke.getWidth(); |
| 318 geometry.fJoin = stroke.isFillStyle() ? SkPaint::Join::kMiter_Join : stroke.
getJoin(); |
| 319 geometry.fMiterLimit = stroke.getMiter(); |
299 | 320 |
300 SkAutoTUnref<GrBatch> batch(AAFlatteningConvexPathBatch::Create(geometry)); | 321 SkAutoTUnref<GrBatch> batch(AAFlatteningConvexPathBatch::Create(geometry)); |
301 target->drawBatch(pipelineBuilder, batch); | 322 target->drawBatch(pipelineBuilder, batch); |
302 | 323 |
303 return true; | 324 return true; |
304 } | 325 } |
305 | 326 |
306 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 327 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
307 | 328 |
308 #ifdef GR_TEST_UTILS | 329 #ifdef GR_TEST_UTILS |
309 | 330 |
310 BATCH_TEST_DEFINE(AAFlatteningConvexPathBatch) { | 331 BATCH_TEST_DEFINE(AAFlatteningConvexPathBatch) { |
311 AAFlatteningConvexPathBatch::Geometry geometry; | 332 AAFlatteningConvexPathBatch::Geometry geometry; |
312 geometry.fColor = GrRandomColor(random); | 333 geometry.fColor = GrRandomColor(random); |
313 geometry.fViewMatrix = GrTest::TestMatrixInvertible(random); | 334 geometry.fViewMatrix = GrTest::TestMatrixInvertible(random); |
314 geometry.fPath = GrTest::TestPathConvex(random); | 335 geometry.fPath = GrTest::TestPathConvex(random); |
315 | 336 |
316 return AAFlatteningConvexPathBatch::Create(geometry); | 337 return AAFlatteningConvexPathBatch::Create(geometry); |
317 } | 338 } |
318 | 339 |
319 #endif | 340 #endif |
OLD | NEW |