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