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

Side by Side Diff: src/gpu/batches/GrAAStrokeRectBatch.cpp

Issue 1282723004: move Stroke Rect and AAFill Rect to their own file (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 4 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/batches/GrAAStrokeRectBatch.h ('k') | src/gpu/batches/GrDrawVerticesBatch.h » ('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 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrAAStrokeRectBatch.h"
9
10 #include "GrDefaultGeoProcFactory.h"
11 #include "GrResourceKey.h"
12 #include "GrResourceProvider.h"
13
14 GR_DECLARE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey);
15 GR_DECLARE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey);
16
17 static void set_inset_fan(SkPoint* pts, size_t stride,
18 const SkRect& r, SkScalar dx, SkScalar dy) {
19 pts->setRectFan(r.fLeft + dx, r.fTop + dy,
20 r.fRight - dx, r.fBottom - dy, stride);
21 }
22
23 static const GrGeometryProcessor* create_stroke_rect_gp(bool tweakAlphaForCovera ge,
24 const SkMatrix& viewMatr ix,
25 bool usesLocalCoords,
26 bool coverageIgnored) {
27 using namespace GrDefaultGeoProcFactory;
28
29 Color color(Color::kAttribute_Type);
30 Coverage::Type coverageType;
31 // TODO remove coverage if coverage is ignored
32 /*if (coverageIgnored) {
33 coverageType = Coverage::kNone_Type;
34 } else*/ if (tweakAlphaForCoverage) {
35 coverageType = Coverage::kSolid_Type;
36 } else {
37 coverageType = Coverage::kAttribute_Type;
38 }
39 Coverage coverage(coverageType);
40 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type :
41 LocalCoords::kUnused_Type);
42 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix);
43 }
44
45
46 void GrAAStrokeRectBatch::initBatchTracker(const GrPipelineInfo& init) {
47 // Handle any color overrides
48 if (!init.readsColor()) {
49 fGeoData[0].fColor = GrColor_ILLEGAL;
50 }
51 init.getOverrideColorIfSet(&fGeoData[0].fColor);
52
53 // setup batch properties
54 fBatch.fColorIgnored = !init.readsColor();
55 fBatch.fColor = fGeoData[0].fColor;
56 fBatch.fUsesLocalCoords = init.readsLocalCoords();
57 fBatch.fCoverageIgnored = !init.readsCoverage();
58 fBatch.fMiterStroke = fGeoData[0].fMiterStroke;
59 fBatch.fCanTweakAlphaForCoverage = init.canTweakAlphaForCoverage();
60 }
61
62 void GrAAStrokeRectBatch::generateGeometry(GrBatchTarget* batchTarget) {
63 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
64
65 SkAutoTUnref<const GrGeometryProcessor> gp(create_stroke_rect_gp(canTweakAlp haForCoverage,
66 this->viewM atrix(),
67 this->usesL ocalCoords(),
68 this->cover ageIgnored()));
69 if (!gp) {
70 SkDebugf("Couldn't create GrGeometryProcessor\n");
71 return;
72 }
73
74 batchTarget->initDraw(gp, this->pipeline());
75
76 size_t vertexStride = gp->getVertexStride();
77
78 SkASSERT(canTweakAlphaForCoverage ?
79 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
80 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCovera geAttr));
81 int innerVertexNum = 4;
82 int outerVertexNum = this->miterStroke() ? 4 : 8;
83 int verticesPerInstance = (outerVertexNum + innerVertexNum) * 2;
84 int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIndexC nt;
85 int instanceCount = fGeoData.count();
86
87 const SkAutoTUnref<const GrIndexBuffer> indexBuffer(
88 GetIndexBuffer(batchTarget->resourceProvider(), this->miterStroke()));
89 InstancedHelper helper;
90 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, vertex Stride,
91 indexBuffer, verticesPerInstance, indicesPerIn stance,
92 instanceCount);
93 if (!vertices || !indexBuffer) {
94 SkDebugf("Could not allocate vertices\n");
95 return;
96 }
97
98 for (int i = 0; i < instanceCount; i++) {
99 const Geometry& args = fGeoData[i];
100 this->generateAAStrokeRectGeometry(vertices,
101 i * verticesPerInstance * vertexStrid e,
102 vertexStride,
103 outerVertexNum,
104 innerVertexNum,
105 args.fColor,
106 args.fDevOutside,
107 args.fDevOutsideAssist,
108 args.fDevInside,
109 args.fMiterStroke,
110 canTweakAlphaForCoverage);
111 }
112 helper.issueDraw(batchTarget);
113 }
114
115 const GrIndexBuffer* GrAAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* res ourceProvider,
116 bool miterStroke) {
117
118 if (miterStroke) {
119 static const uint16_t gMiterIndices[] = {
120 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
121 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
122 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
123 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
124
125 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
126 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
127 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
128 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
129
130 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
131 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
132 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
133 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
134 };
135 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gMiterIndices) == kMiterIndexCnt);
136 GR_DEFINE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey);
137 return resourceProvider->findOrCreateInstancedIndexBuffer(gMiterIndices,
138 kMiterIndexCnt, kNumMiterRectsInIndexBuffer, kMiterVertexCnt,
139 gMiterIndexBufferKey);
140 } else {
141 /**
142 * As in miter-stroke, index = a + b, and a is the current index, b is t he shift
143 * from the first index. The index layout:
144 * outer AA line: 0~3, 4~7
145 * outer edge: 8~11, 12~15
146 * inner edge: 16~19
147 * inner AA line: 20~23
148 * Following comes a bevel-stroke rect and its indices:
149 *
150 * 4 7
151 * *********************************
152 * * ______________________________ *
153 * * / 12 15 \ *
154 * * / \ *
155 * 0 * |8 16_____________________19 11 | * 3
156 * * | | | | *
157 * * | | **************** | | *
158 * * | | * 20 23 * | | *
159 * * | | * * | | *
160 * * | | * 21 22 * | | *
161 * * | | **************** | | *
162 * * | |____________________| | *
163 * 1 * |9 17 18 10| * 2
164 * * \ / *
165 * * \13 __________________________14/ *
166 * * *
167 * **********************************
168 * 5 6
169 */
170 static const uint16_t gBevelIndices[] = {
171 // Draw outer AA, from outer AA line to outer edge, shift is 0.
172 0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0,
173 1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0,
174 5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0,
175 6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0,
176 2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0,
177 3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0,
178 7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0,
179 4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0,
180
181 // Draw the stroke, from outer edge to inner edge, shift is 8.
182 0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8,
183 1 + 8, 5 + 8, 9 + 8,
184 5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8,
185 6 + 8, 2 + 8, 10 + 8,
186 2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8,
187 3 + 8, 7 + 8, 11 + 8,
188 7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8,
189 4 + 8, 0 + 8, 8 + 8,
190
191 // Draw the inner AA, from inner edge to inner AA line, shift is 16.
192 0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16,
193 1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16,
194 2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16,
195 3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16,
196 };
197 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gBevelIndices) == kBevelIndexCnt);
198
199 GR_DEFINE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey);
200 return resourceProvider->findOrCreateInstancedIndexBuffer(gBevelIndices,
201 kBevelIndexCnt, kNumBevelRectsInIndexBuffer, kBevelVertexCnt,
202 gBevelIndexBufferKey);
203 }
204 }
205
206 bool GrAAStrokeRectBatch::onCombineIfPossible(GrBatch* t) {
207 if (!this->pipeline()->isEqual(*t->pipeline())) {
208 return false;
209 }
210
211 GrAAStrokeRectBatch* that = t->cast<GrAAStrokeRectBatch>();
212
213 // TODO batch across miterstroke changes
214 if (this->miterStroke() != that->miterStroke()) {
215 return false;
216 }
217
218 // We apply the viewmatrix to the rect points on the cpu. However, if the p ipeline uses
219 // local coords then we won't be able to batch. We could actually upload th e viewmatrix
220 // using vertex attributes in these cases, but haven't investigated that
221 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMa trix())) {
222 return false;
223 }
224
225 // In the event of two batches, one who can tweak, one who cannot, we just f all back to
226 // not tweaking
227 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) {
228 fBatch.fCanTweakAlphaForCoverage = false;
229 }
230
231 if (this->color() != that->color()) {
232 fBatch.fColor = GrColor_ILLEGAL;
233 }
234 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
235 this->joinBounds(that->bounds());
236 return true;
237 }
238
239 void GrAAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices,
240 size_t offset,
241 size_t vertexStride,
242 int outerVertexNum,
243 int innerVertexNum,
244 GrColor color,
245 const SkRect& devOutside,
246 const SkRect& devOutsideA ssist,
247 const SkRect& devInside,
248 bool miterStroke,
249 bool tweakAlphaForCoverag e) const {
250 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset;
251
252 // We create vertices for four nested rectangles. There are two ramps from 0 to full
253 // coverage, one on the exterior of the stroke and the other on the interior .
254 // The following pointers refer to the four rects, from outermost to innermo st.
255 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
256 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * verte xStride);
257 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * v ertexStride);
258 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts +
259 (2 * outerVertexNum + innerVer texNum) *
260 vertexStride);
261
262 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
263 // TODO: this only really works if the X & Y margins are the same all around
264 // the rect (or if they are all >= 1.0).
265 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRigh t);
266 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
267 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
268 if (miterStroke) {
269 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInsid e.fBottom);
270 } else {
271 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom -
272 devInside.fBottom);
273 }
274 SkASSERT(inset >= 0);
275 #else
276 SkScalar inset = SK_ScalarHalf;
277 #endif
278
279 if (miterStroke) {
280 // outermost
281 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK_Sca larHalf);
282 // inner two
283 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset);
284 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset);
285 // innermost
286 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK_Sca larHalf);
287 } else {
288 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vertexSt ride);
289 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts +
290 (outerVertexNum + 4) *
291 vertexStride);
292 // outermost
293 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK_Sca larHalf);
294 set_inset_fan(fan0AssistPos, vertexStride, devOutsideAssist, -SK_ScalarH alf,
295 -SK_ScalarHalf);
296 // outer one of the inner two
297 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset);
298 set_inset_fan(fan1AssistPos, vertexStride, devOutsideAssist, inset, in set);
299 // inner one of the inner two
300 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset);
301 // innermost
302 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK_Sca larHalf);
303 }
304
305 // Make verts point to vertex color and then set all the color and coverage vertex attrs
306 // values. The outermost rect has 0 coverage
307 verts += sizeof(SkPoint);
308 for (int i = 0; i < outerVertexNum; ++i) {
309 if (tweakAlphaForCoverage) {
310 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
311 } else {
312 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
313 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) = 0;
314 }
315 }
316
317 // scale is the coverage for the the inner two rects.
318 int scale;
319 if (inset < SK_ScalarHalf) {
320 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
321 SkASSERT(scale >= 0 && scale <= 255);
322 } else {
323 scale = 0xff;
324 }
325
326 float innerCoverage = GrNormalizeByteToFloat(scale);
327 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
328
329 verts += outerVertexNum * vertexStride;
330 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
331 if (tweakAlphaForCoverage) {
332 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
333 } else {
334 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
335 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) =
336 innerCoverage;
337 }
338 }
339
340 // The innermost rect has 0 coverage
341 verts += (outerVertexNum + innerVertexNum) * vertexStride;
342 for (int i = 0; i < innerVertexNum; ++i) {
343 if (tweakAlphaForCoverage) {
344 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
345 } else {
346 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
347 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(GrColo r)) = 0;
348 }
349 }
350 }
351
352 //////////////////////////////////////////////////////////////////////////////// ///////////////////
353
354 #ifdef GR_TEST_UTILS
355
356 #include "GrBatchTest.h"
357
358 BATCH_TEST_DEFINE(AAStrokeRectBatch) {
359 bool miterStroke = random->nextBool();
360
361 // Create mock stroke rect
362 SkRect outside = GrTest::TestRect(random);
363 SkScalar minDim = SkMinScalar(outside.width(), outside.height());
364 SkScalar strokeWidth = minDim * 0.1f;
365 SkRect outsideAssist = outside;
366 outsideAssist.outset(strokeWidth, strokeWidth);
367 SkRect inside = outside;
368 inside.inset(strokeWidth, strokeWidth);
369
370 GrAAStrokeRectBatch::Geometry geo;
371 geo.fColor = GrRandomColor(random);
372 geo.fDevOutside = outside;
373 geo.fDevOutsideAssist = outsideAssist;
374 geo.fDevInside = inside;
375 geo.fMiterStroke = miterStroke;
376
377 return GrAAStrokeRectBatch::Create(geo, GrTest::TestMatrix(random));
378 }
379
380 #endif
OLDNEW
« no previous file with comments | « src/gpu/batches/GrAAStrokeRectBatch.h ('k') | src/gpu/batches/GrDrawVerticesBatch.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698