Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(818)

Side by Side Diff: src/gpu/GrAALinearizingConvexPathRenderer.cpp

Issue 1306143005: Move Pathrenderers to batches folder (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrAALinearizingConvexPathRenderer.h ('k') | src/gpu/GrAddPathRenderers_default.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1
2 /*
3 * Copyright 2015 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 "GrAALinearizingConvexPathRenderer.h"
10
11 #include "GrAAConvexTessellator.h"
12 #include "GrBatchFlushState.h"
13 #include "GrBatchTest.h"
14 #include "GrContext.h"
15 #include "GrDefaultGeoProcFactory.h"
16 #include "GrGeometryProcessor.h"
17 #include "GrInvariantOutput.h"
18 #include "GrPathUtils.h"
19 #include "GrProcessor.h"
20 #include "GrPipelineBuilder.h"
21 #include "GrStrokeInfo.h"
22 #include "SkGeometry.h"
23 #include "SkString.h"
24 #include "SkTraceEvent.h"
25 #include "SkPathPriv.h"
26 #include "batches/GrVertexBatch.h"
27 #include "gl/GrGLProcessor.h"
28 #include "gl/GrGLGeometryProcessor.h"
29 #include "gl/builders/GrGLProgramBuilder.h"
30
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;
36
37 GrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() {
38 }
39
40 ///////////////////////////////////////////////////////////////////////////////
41
42 bool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& arg s) const {
43 if (!args.fAntiAlias) {
44 return false;
45 }
46 if (args.fPath->isInverseFillType()) {
47 return false;
48 }
49 if (!args.fPath->isConvex()) {
50 return false;
51 }
52 if (args.fStroke->getStyle() == SkStrokeRec::kStroke_Style) {
53 if (!args.fViewMatrix->isSimilarity()) {
54 return false;
55 }
56 SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * args.fStroke->g etWidth();
57 return strokeWidth >= 1.0f && strokeWidth <= kMaxStrokeWidth && !args.fS troke->isDashed() &&
58 SkPathPriv::LastVerbIsClose(*args.fPath) &&
59 args.fStroke->getJoin() != SkPaint::Join::kRound_Join;
60 }
61 return args.fStroke->getStyle() == SkStrokeRec::kFill_Style;
62 }
63
64 // extract the result vertices and indices from the GrAAConvexTessellator
65 static void extract_verts(const GrAAConvexTessellator& tess,
66 void* vertices,
67 size_t vertexStride,
68 GrColor color,
69 uint16_t firstIndex,
70 uint16_t* idxs,
71 bool tweakAlphaForCoverage) {
72 intptr_t verts = reinterpret_cast<intptr_t>(vertices);
73
74 for (int i = 0; i < tess.numPts(); ++i) {
75 *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i);
76 }
77
78 // Make 'verts' point to the colors
79 verts += sizeof(SkPoint);
80 for (int i = 0; i < tess.numPts(); ++i) {
81 if (tweakAlphaForCoverage) {
82 SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255);
83 unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i));
84 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, s cale);
85 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
86 } else {
87 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
88 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) =
89 tess.coverage(i);
90 }
91 }
92
93 for (int i = 0; i < tess.numIndices(); ++i) {
94 idxs[i] = tess.index(i) + firstIndex;
95 }
96 }
97
98 static const GrGeometryProcessor* create_fill_gp(bool tweakAlphaForCoverage,
99 const SkMatrix& viewMatrix,
100 bool usesLocalCoords,
101 bool coverageIgnored) {
102 using namespace GrDefaultGeoProcFactory;
103
104 Color color(Color::kAttribute_Type);
105 Coverage::Type coverageType;
106 // TODO remove coverage if coverage is ignored
107 /*if (coverageIgnored) {
108 coverageType = Coverage::kNone_Type;
109 } else*/ if (tweakAlphaForCoverage) {
110 coverageType = Coverage::kSolid_Type;
111 } else {
112 coverageType = Coverage::kAttribute_Type;
113 }
114 Coverage coverage(coverageType);
115 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type :
116 LocalCoords::kUnused_Type);
117 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix);
118 }
119
120 class AAFlatteningConvexPathBatch : public GrVertexBatch {
121 public:
122 struct Geometry {
123 GrColor fColor;
124 SkMatrix fViewMatrix;
125 SkPath fPath;
126 SkScalar fStrokeWidth;
127 SkPaint::Join fJoin;
128 SkScalar fMiterLimit;
129 };
130
131 static GrDrawBatch* Create(const Geometry& geometry) {
132 return new AAFlatteningConvexPathBatch(geometry);
133 }
134
135 const char* name() const override { return "AAConvexBatch"; }
136
137 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
138 // When this is called on a batch, there is only one geometry bundle
139 out->setKnownFourComponents(fGeoData[0].fColor);
140 }
141 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
142 out->setUnknownSingleComponent();
143 }
144
145 private:
146 void initBatchTracker(const GrPipelineOptimizations& opt) override {
147 // Handle any color overrides
148 if (!opt.readsColor()) {
149 fGeoData[0].fColor = GrColor_ILLEGAL;
150 }
151 opt.getOverrideColorIfSet(&fGeoData[0].fColor);
152
153 // setup batch properties
154 fBatch.fColorIgnored = !opt.readsColor();
155 fBatch.fColor = fGeoData[0].fColor;
156 fBatch.fUsesLocalCoords = opt.readsLocalCoords();
157 fBatch.fCoverageIgnored = !opt.readsCoverage();
158 fBatch.fLinesOnly = SkPath::kLine_SegmentMask == fGeoData[0].fPath.getSe gmentMasks();
159 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage();
160 }
161
162 void draw(GrVertexBatch::Target* target, const GrPipeline* pipeline, int ver texCount,
163 size_t vertexStride, void* vertices, int indexCount, uint16_t* indic es) {
164 if (vertexCount == 0 || indexCount == 0) {
165 return;
166 }
167 const GrVertexBuffer* vertexBuffer;
168 GrVertices info;
169 int firstVertex;
170 void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertex Buffer,
171 &firstVertex);
172 if (!verts) {
173 SkDebugf("Could not allocate vertices\n");
174 return;
175 }
176 memcpy(verts, vertices, vertexCount * vertexStride);
177
178 const GrIndexBuffer* indexBuffer;
179 int firstIndex;
180 uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &first Index);
181 if (!idxs) {
182 SkDebugf("Could not allocate indices\n");
183 return;
184 }
185 memcpy(idxs, indices, indexCount * sizeof(uint16_t));
186 info.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex,
187 firstIndex, vertexCount, indexCount);
188 target->draw(info);
189 }
190
191 void onPrepareDraws(Target* target) override {
192 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
193
194 // Setup GrGeometryProcessor
195 SkAutoTUnref<const GrGeometryProcessor> gp(create_fill_gp(canTweakAlphaF orCoverage,
196 this->viewMatr ix(),
197 this->usesLoca lCoords(),
198 this->coverage Ignored()));
199 if (!gp) {
200 SkDebugf("Couldn't create a GrGeometryProcessor\n");
201 return;
202 }
203
204 target->initDraw(gp, this->pipeline());
205
206 size_t vertexStride = gp->getVertexStride();
207
208 SkASSERT(canTweakAlphaForCoverage ?
209 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) :
210 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr));
211
212 int instanceCount = fGeoData.count();
213
214 int vertexCount = 0;
215 int indexCount = 0;
216 int maxVertices = DEFAULT_BUFFER_SIZE;
217 int maxIndices = DEFAULT_BUFFER_SIZE;
218 uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStrid e);
219 uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint 16_t));
220 for (int i = 0; i < instanceCount; i++) {
221 Geometry& args = fGeoData[i];
222 GrAAConvexTessellator tess(args.fStrokeWidth, args.fJoin, args.fMite rLimit);
223
224 if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
225 continue;
226 }
227
228 int currentIndices = tess.numIndices();
229 SkASSERT(currentIndices <= UINT16_MAX);
230 if (indexCount + currentIndices > UINT16_MAX) {
231 // if we added the current instance, we would overflow the indic es we can store in a
232 // uint16_t. Draw what we've got so far and reset.
233 draw(target, this->pipeline(), vertexCount, vertexStride, vertic es, indexCount,
234 indices);
235 vertexCount = 0;
236 indexCount = 0;
237 }
238 int currentVertices = tess.numPts();
239 if (vertexCount + currentVertices > maxVertices) {
240 maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2);
241 vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * v ertexStride);
242 }
243 if (indexCount + currentIndices > maxIndices) {
244 maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2) ;
245 indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * siz eof(uint16_t));
246 }
247
248 extract_verts(tess, vertices + vertexStride * vertexCount, vertexStr ide, args.fColor,
249 vertexCount, indices + indexCount, canTweakAlphaForCoverage) ;
250 vertexCount += currentVertices;
251 indexCount += currentIndices;
252 }
253 draw(target, this->pipeline(), vertexCount, vertexStride, vertices, inde xCount,
254 indices);
255 sk_free(vertices);
256 sk_free(indices);
257 }
258
259 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
260
261 AAFlatteningConvexPathBatch(const Geometry& geometry) {
262 this->initClassID<AAFlatteningConvexPathBatch>();
263 fGeoData.push_back(geometry);
264
265 // compute bounds
266 fBounds = geometry.fPath.getBounds();
267 geometry.fViewMatrix.mapRect(&fBounds);
268 }
269
270 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
271 AAFlatteningConvexPathBatch* that = t->cast<AAFlatteningConvexPathBatch> ();
272 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
273 that->bounds(), caps)) {
274 return false;
275 }
276
277 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
278 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
279 return false;
280 }
281
282 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to
283 // not tweaking
284 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) {
285 fBatch.fCanTweakAlphaForCoverage = false;
286 }
287
288 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
289 this->joinBounds(that->bounds());
290 return true;
291 }
292
293 GrColor color() const { return fBatch.fColor; }
294 bool linesOnly() const { return fBatch.fLinesOnly; }
295 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
296 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover age; }
297 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
298 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
299
300 struct BatchTracker {
301 GrColor fColor;
302 bool fUsesLocalCoords;
303 bool fColorIgnored;
304 bool fCoverageIgnored;
305 bool fLinesOnly;
306 bool fCanTweakAlphaForCoverage;
307 };
308
309 BatchTracker fBatch;
310 SkSTArray<1, Geometry, true> fGeoData;
311 };
312
313 bool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
314 if (args.fPath->isEmpty()) {
315 return true;
316 }
317 AAFlatteningConvexPathBatch::Geometry geometry;
318 geometry.fColor = args.fColor;
319 geometry.fViewMatrix = *args.fViewMatrix;
320 geometry.fPath = *args.fPath;
321 geometry.fStrokeWidth = args.fStroke->isFillStyle() ? -1.0f : args.fStroke-> getWidth();
322 geometry.fJoin = args.fStroke->isFillStyle() ? SkPaint::Join::kMiter_Join :
323 args.fStroke->getJoin();
324 geometry.fMiterLimit = args.fStroke->getMiter();
325
326 SkAutoTUnref<GrDrawBatch> batch(AAFlatteningConvexPathBatch::Create(geometry ));
327 args.fTarget->drawBatch(*args.fPipelineBuilder, batch);
328
329 return true;
330 }
331
332 //////////////////////////////////////////////////////////////////////////////// ///////////////////
333
334 #ifdef GR_TEST_UTILS
335
336 DRAW_BATCH_TEST_DEFINE(AAFlatteningConvexPathBatch) {
337 AAFlatteningConvexPathBatch::Geometry geometry;
338 geometry.fColor = GrRandomColor(random);
339 geometry.fViewMatrix = GrTest::TestMatrixInvertible(random);
340 geometry.fPath = GrTest::TestPathConvex(random);
341
342 return AAFlatteningConvexPathBatch::Create(geometry);
343 }
344
345 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrAALinearizingConvexPathRenderer.h ('k') | src/gpu/GrAddPathRenderers_default.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698