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