OLD | NEW |
---|---|
(Empty) | |
1 | |
2 /* | |
robertphillips
2015/05/27 18:10:53
Update this ?
ethannicholas
2015/05/27 19:22:30
Done.
| |
3 * Copyright 2012 Google Inc. | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 | |
9 #include "GrAAFlatteningConvexPathRenderer.h" | |
10 | |
11 #include "GrAAFlatteningConvexTessellator.h" | |
12 #include "GrBatch.h" | |
13 #include "GrBatchTarget.h" | |
14 #include "GrBatchTest.h" | |
15 #include "GrContext.h" | |
16 #include "GrDefaultGeoProcFactory.h" | |
17 #include "GrGeometryProcessor.h" | |
18 #include "GrInvariantOutput.h" | |
19 #include "GrPathUtils.h" | |
20 #include "GrProcessor.h" | |
21 #include "GrPipelineBuilder.h" | |
22 #include "GrStrokeInfo.h" | |
23 #include "SkGeometry.h" | |
24 #include "SkString.h" | |
25 #include "SkTraceEvent.h" | |
26 #include "gl/GrGLProcessor.h" | |
27 #include "gl/GrGLSL.h" | |
28 #include "gl/GrGLGeometryProcessor.h" | |
29 #include "gl/builders/GrGLProgramBuilder.h" | |
30 | |
31 #define DEFAULT_BUFFER_SIZE 100 | |
32 | |
33 GrAAFlatteningConvexPathRenderer::GrAAFlatteningConvexPathRenderer() { | |
34 } | |
35 | |
36 /////////////////////////////////////////////////////////////////////////////// | |
37 | |
38 bool GrAAFlatteningConvexPathRenderer::canDrawPath(const GrDrawTarget* target, | |
robertphillips
2015/05/27 18:10:54
Align these guys ?
ethannicholas
2015/05/27 19:22:30
Done.
| |
39 const GrPipelineBuilder*, | |
40 const SkMatrix& viewMatrix, | |
41 const SkPath& path, | |
42 const GrStrokeInfo& stroke, | |
43 bool antiAlias) const { | |
44 return (target->caps()->shaderCaps()->shaderDerivativeSupport() && antiAlias && | |
bsalomon
2015/05/27 17:11:07
probably don't need shader derivative support anym
ethannicholas
2015/05/27 19:22:30
Done.
| |
45 stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex() ); | |
46 } | |
47 | |
48 // extract the result vertices and indices from the GrAAFlatteningConvexTessella tor | |
49 static void extract_verts(const GrAAFlatteningConvexTessellator& tess, | |
50 void* vertices, | |
51 size_t vertexStride, | |
52 GrColor color, | |
53 uint16_t firstIndex, | |
54 uint16_t* idxs, | |
55 bool tweakAlphaForCoverage) { | |
56 intptr_t verts = reinterpret_cast<intptr_t>(vertices); | |
57 | |
58 for (int i = 0; i < tess.numPts(); ++i) { | |
59 *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i); | |
60 } | |
61 | |
62 // Make 'verts' point to the colors | |
63 verts += sizeof(SkPoint); | |
64 for (int i = 0; i < tess.numPts(); ++i) { | |
65 SkASSERT(tess.depth(i) >= -0.5f && tess.depth(i) <= 0.5f); | |
66 if (tweakAlphaForCoverage) { | |
67 SkASSERT(SkScalarRoundToInt(255.0f * (tess.depth(i) + 0.5f)) <= 255) ; | |
68 unsigned scale = SkScalarRoundToInt(255.0f * (tess.depth(i) + 0.5f)) ; | |
69 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, s cale); | |
70 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; | |
71 } else { | |
72 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | |
73 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) = | |
74 tess.depth(i ) + 0.5f; | |
75 } | |
76 } | |
77 | |
78 for (int i = 0; i < tess.numIndices(); ++i) { | |
79 idxs[i] = tess.index(i) + firstIndex; | |
80 } | |
81 } | |
82 | |
83 static const GrGeometryProcessor* create_fill_gp(bool tweakAlphaForCoverage, | |
84 const SkMatrix& localMatrix, | |
85 bool usesLocalCoords, | |
86 bool coverageIgnored) { | |
87 uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType; | |
88 if (!tweakAlphaForCoverage) { | |
89 flags |= GrDefaultGeoProcFactory::kCoverage_GPType; | |
90 } | |
91 | |
92 return GrDefaultGeoProcFactory::Create(flags, GrColor_WHITE, usesLocalCoords , coverageIgnored, | |
93 SkMatrix::I(), localMatrix); | |
94 } | |
95 | |
96 class AAFlatteningConvexPathBatch : public GrBatch { | |
97 public: | |
98 struct Geometry { | |
99 GrColor fColor; | |
100 SkMatrix fViewMatrix; | |
101 SkPath fPath; | |
102 }; | |
103 | |
104 static GrBatch* Create(const Geometry& geometry) { | |
105 return SkNEW_ARGS(AAFlatteningConvexPathBatch, (geometry)); | |
106 } | |
107 | |
108 const char* name() const override { return "AAConvexBatch"; } | |
109 | |
110 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | |
111 // When this is called on a batch, there is only one geometry bundle | |
112 out->setKnownFourComponents(fGeoData[0].fColor); | |
113 } | |
114 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { | |
115 out->setUnknownSingleComponent(); | |
116 } | |
117 | |
118 void initBatchTracker(const GrPipelineInfo& init) override { | |
119 // Handle any color overrides | |
120 if (init.fColorIgnored) { | |
121 fGeoData[0].fColor = GrColor_ILLEGAL; | |
122 } else if (GrColor_ILLEGAL != init.fOverrideColor) { | |
123 fGeoData[0].fColor = init.fOverrideColor; | |
124 } | |
125 | |
126 // setup batch properties | |
127 fBatch.fColorIgnored = init.fColorIgnored; | |
128 fBatch.fColor = fGeoData[0].fColor; | |
129 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; | |
130 fBatch.fCoverageIgnored = init.fCoverageIgnored; | |
131 fBatch.fLinesOnly = SkPath::kLine_SegmentMask == fGeoData[0].fPath.getSe gmentMasks(); | |
132 fBatch.fCanTweakAlphaForCoverage = init.fCanTweakAlphaForCoverage; | |
133 } | |
134 | |
135 void draw(GrBatchTarget* batchTarget, const GrPipeline* pipeline, int vertex Count, | |
136 size_t vertexStride, void* vertices, int indexCount, uint16_t* indic es) { | |
137 if (vertexCount == 0 || indexCount == 0) { | |
138 return; | |
139 } | |
140 const GrVertexBuffer* vertexBuffer; | |
141 GrVertices info; | |
142 int firstVertex; | |
143 void* verts = batchTarget->makeVertSpace(vertexStride, vertexCount, &ver texBuffer, | |
144 &firstVertex); | |
145 if (!verts) { | |
146 SkDebugf("Could not allocate vertices\n"); | |
147 return; | |
148 } | |
149 memcpy(verts, vertices, vertexCount * vertexStride); | |
150 | |
151 const GrIndexBuffer* indexBuffer; | |
152 int firstIndex; | |
153 uint16_t* idxs = batchTarget->makeIndexSpace(indexCount, &indexBuffer, & firstIndex); | |
154 if (!idxs) { | |
155 SkDebugf("Could not allocate indices\n"); | |
156 return; | |
157 } | |
158 memcpy(idxs, indices, indexCount * sizeof(uint16_t)); | |
159 info.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, | |
160 firstIndex, vertexCount, indexCount); | |
161 batchTarget->draw(info); | |
162 } | |
163 | |
164 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override { | |
165 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); | |
166 | |
167 SkMatrix invert; | |
168 if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) { | |
169 SkDebugf("Could not invert viewmatrix\n"); | |
170 return; | |
171 } | |
172 | |
173 // Setup GrGeometryProcessor | |
174 SkAutoTUnref<const GrGeometryProcessor> gp( | |
175 create_fill_gp(canTweakAlphaForC overage, invert, | |
176 this->usesLocalCo ords(), | |
177 this->coverageIgn ored())); | |
178 | |
179 batchTarget->initDraw(gp, pipeline); | |
180 | |
181 size_t vertexStride = gp->getVertexStride(); | |
182 | |
183 SkASSERT(canTweakAlphaForCoverage ? | |
184 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : | |
185 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr)); | |
186 | |
187 GrAAFlatteningConvexTessellator tess; | |
188 | |
189 int instanceCount = fGeoData.count(); | |
190 | |
191 int vertexCount = 0; | |
192 int indexCount = 0; | |
193 int maxVertices = DEFAULT_BUFFER_SIZE; | |
194 int maxIndices = DEFAULT_BUFFER_SIZE; | |
195 uint8_t* vertices = (uint8_t*) malloc(maxVertices * vertexStride); | |
196 uint16_t* indices = (uint16_t*) malloc(maxIndices * sizeof(uint16_t)); | |
197 for (int i = 0; i < instanceCount; i++) { | |
198 tess.rewind(); | |
199 | |
200 Geometry& args = fGeoData[i]; | |
201 | |
202 if (!tess.tessellate(args.fViewMatrix, args.fPath)) { | |
203 continue; | |
204 } | |
205 | |
206 #define MAX(a, b) (a > b ? a : b) | |
bsalomon
2015/05/27 17:11:07
There is an SkTMax
ethannicholas
2015/05/27 19:22:30
Done.
| |
207 | |
208 int currentIndices = tess.numIndices(); | |
209 SkASSERT(currentIndices <= UINT16_MAX); | |
210 if (indexCount + currentIndices > UINT16_MAX) { | |
211 // if we added the current instance, we would overflow the indic es we can store in a | |
212 // uint16_t. Draw what we've got so far and reset. | |
213 draw(batchTarget, pipeline, vertexCount, vertexStride, vertices, indexCount, | |
214 indices); | |
215 vertexCount = 0; | |
216 indexCount = 0; | |
217 } | |
218 int currentVertices = tess.numPts(); | |
219 if (vertexCount + currentVertices > maxVertices) { | |
220 maxVertices = MAX(vertexCount + currentVertices, maxVertices * 2 ); | |
221 vertices = (uint8_t*) realloc(vertices, maxVertices * vertexStri de); | |
222 } | |
223 if (indexCount + currentIndices > maxIndices) { | |
224 maxIndices = MAX(indexCount + currentIndices, maxIndices * 2); | |
225 indices = (uint16_t*) realloc(indices, maxIndices * sizeof(uint1 6_t)); | |
226 } | |
227 | |
228 #undef MAX | |
229 | |
230 extract_verts(tess, vertices + vertexStride * vertexCount, vertexStr ide, args.fColor, | |
231 vertexCount, indices + indexCount, canTweakAlphaForCoverage) ; | |
232 vertexCount += currentVertices; | |
233 indexCount += currentIndices; | |
234 } | |
235 draw(batchTarget, pipeline, vertexCount, vertexStride, vertices, indexCo unt, indices); | |
236 free(vertices); | |
237 free(indices); | |
238 } | |
239 | |
240 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
241 | |
242 private: | |
243 AAFlatteningConvexPathBatch(const Geometry& geometry) { | |
244 this->initClassID<AAFlatteningConvexPathBatch>(); | |
245 fGeoData.push_back(geometry); | |
246 | |
247 // compute bounds | |
248 fBounds = geometry.fPath.getBounds(); | |
249 geometry.fViewMatrix.mapRect(&fBounds); | |
250 } | |
251 | |
252 bool onCombineIfPossible(GrBatch* t) override { | |
253 AAFlatteningConvexPathBatch* that = t->cast<AAFlatteningConvexPathBatch> (); | |
254 | |
255 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | |
256 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) { | |
257 return false; | |
258 } | |
259 | |
260 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to | |
261 // not tweaking | |
262 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) { | |
263 fBatch.fCanTweakAlphaForCoverage = false; | |
264 } | |
265 | |
266 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; | |
267 this->joinBounds(that->bounds()); | |
268 return true; | |
269 } | |
270 | |
271 GrColor color() const { return fBatch.fColor; } | |
272 bool linesOnly() const { return fBatch.fLinesOnly; } | |
273 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
274 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover age; } | |
275 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
276 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } | |
277 | |
278 struct BatchTracker { | |
279 GrColor fColor; | |
280 bool fUsesLocalCoords; | |
281 bool fColorIgnored; | |
282 bool fCoverageIgnored; | |
283 bool fLinesOnly; | |
284 bool fCanTweakAlphaForCoverage; | |
285 }; | |
286 | |
287 BatchTracker fBatch; | |
288 SkSTArray<1, Geometry, true> fGeoData; | |
289 }; | |
290 | |
291 bool GrAAFlatteningConvexPathRenderer::onDrawPath(GrDrawTarget* target, | |
292 GrPipelineBuilder* pipelineBuilder, | |
293 GrColor color, | |
294 const SkMatrix& vm, | |
295 const SkPath& path, | |
296 const GrStrokeInfo&, | |
297 bool antiAlias) { | |
298 if (path.isEmpty()) { | |
299 return true; | |
300 } | |
301 AAFlatteningConvexPathBatch::Geometry geometry; | |
302 geometry.fColor = color; | |
303 geometry.fViewMatrix = vm; | |
304 geometry.fPath = path; | |
305 | |
306 SkAutoTUnref<GrBatch> batch(AAFlatteningConvexPathBatch::Create(geometry)); | |
307 target->drawBatch(pipelineBuilder, batch); | |
308 | |
309 return true; | |
310 } | |
311 | |
312 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
313 | |
314 #ifdef GR_TEST_UTILS | |
315 | |
316 BATCH_TEST_DEFINE(AAFlatteningConvexPathBatch) { | |
317 AAFlatteningConvexPathBatch::Geometry geometry; | |
318 geometry.fColor = GrRandomColor(random); | |
319 geometry.fViewMatrix = GrTest::TestMatrixInvertible(random); | |
320 geometry.fPath = GrTest::TestPathConvex(random); | |
321 | |
322 return AAFlatteningConvexPathBatch::Create(geometry); | |
323 } | |
324 | |
325 #endif | |
OLD | NEW |