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

Side by Side Diff: src/gpu/GrAARectRenderer.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 | « gyp/gpu.gypi ('k') | src/gpu/batches/GrAAFillRectBatch.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrAARectRenderer.h" 8 #include "GrAARectRenderer.h"
9 #include "GrBatchTarget.h" 9 #include "GrBatchTarget.h"
10 #include "GrBatchTest.h" 10 #include "GrBatchTest.h"
11 #include "GrContext.h" 11 #include "GrContext.h"
12 #include "GrDefaultGeoProcFactory.h"
13 #include "GrDrawTarget.h" 12 #include "GrDrawTarget.h"
14 #include "GrGeometryProcessor.h" 13 #include "GrGeometryProcessor.h"
15 #include "GrInvariantOutput.h" 14 #include "GrInvariantOutput.h"
16 #include "GrResourceKey.h"
17 #include "GrResourceProvider.h"
18 #include "GrTestUtils.h" 15 #include "GrTestUtils.h"
19 #include "GrVertexBuffer.h" 16 #include "GrVertexBuffer.h"
20 #include "SkColorPriv.h" 17 #include "SkColorPriv.h"
21 #include "batches/GrBatch.h" 18 #include "batches/GrAAFillRectBatch.h"
19 #include "batches/GrAAStrokeRectBatch.h"
22 #include "gl/GrGLProcessor.h" 20 #include "gl/GrGLProcessor.h"
23 #include "gl/GrGLGeometryProcessor.h" 21 #include "gl/GrGLGeometryProcessor.h"
24 #include "gl/builders/GrGLProgramBuilder.h" 22 #include "gl/builders/GrGLProgramBuilder.h"
25 23
26 /////////////////////////////////////////////////////////////////////////////// 24 ///////////////////////////////////////////////////////////////////////////////
27 25
28 static void set_inset_fan(SkPoint* pts, size_t stride,
29 const SkRect& r, SkScalar dx, SkScalar dy) {
30 pts->setRectFan(r.fLeft + dx, r.fTop + dy,
31 r.fRight - dx, r.fBottom - dy, stride);
32 }
33
34 static const GrGeometryProcessor* create_fill_rect_gp(bool tweakAlphaForCoverage ,
35 const SkMatrix& viewMatrix ,
36 bool usesLocalCoords,
37 bool coverageIgnored) {
38 using namespace GrDefaultGeoProcFactory;
39
40 Color color(Color::kAttribute_Type);
41 Coverage::Type coverageType;
42 // TODO remove coverage if coverage is ignored
43 /*if (coverageIgnored) {
44 coverageType = Coverage::kNone_Type;
45 } else*/ if (tweakAlphaForCoverage) {
46 coverageType = Coverage::kSolid_Type;
47 } else {
48 coverageType = Coverage::kAttribute_Type;
49 }
50 Coverage coverage(coverageType);
51 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type :
52 LocalCoords::kUnused_Type);
53 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix);
54 }
55
56 GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
57
58 class AAFillRectBatch : public GrBatch {
59 public:
60 struct Geometry {
61 GrColor fColor;
62 SkMatrix fViewMatrix;
63 SkRect fRect;
64 SkRect fDevRect;
65 };
66
67 static GrBatch* Create(const Geometry& geometry) {
68 return SkNEW_ARGS(AAFillRectBatch, (geometry));
69 }
70
71 const char* name() const override { return "AAFillRectBatch"; }
72
73 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
74 // When this is called on a batch, there is only one geometry bundle
75 out->setKnownFourComponents(fGeoData[0].fColor);
76 }
77
78 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
79 out->setUnknownSingleComponent();
80 }
81
82 void initBatchTracker(const GrPipelineInfo& init) override {
83 // Handle any color overrides
84 if (!init.readsColor()) {
85 fGeoData[0].fColor = GrColor_ILLEGAL;
86 }
87 init.getOverrideColorIfSet(&fGeoData[0].fColor);
88
89 // setup batch properties
90 fBatch.fColorIgnored = !init.readsColor();
91 fBatch.fColor = fGeoData[0].fColor;
92 fBatch.fUsesLocalCoords = init.readsLocalCoords();
93 fBatch.fCoverageIgnored = !init.readsCoverage();
94 fBatch.fCanTweakAlphaForCoverage = init.canTweakAlphaForCoverage();
95 }
96
97 void generateGeometry(GrBatchTarget* batchTarget) override {
98 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
99
100 SkAutoTUnref<const GrGeometryProcessor> gp(create_fill_rect_gp(canTweakA lphaForCoverage,
101 this->vie wMatrix(),
102 this->use sLocalCoords(),
103 this->cov erageIgnored()));
104 if (!gp) {
105 SkDebugf("Couldn't create GrGeometryProcessor\n");
106 return;
107 }
108
109 batchTarget->initDraw(gp, this->pipeline());
110
111 size_t vertexStride = gp->getVertexStride();
112 SkASSERT(canTweakAlphaForCoverage ?
113 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) :
114 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr));
115 int instanceCount = fGeoData.count();
116
117 SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer(
118 batchTarget->resourceProvider()));
119 InstancedHelper helper;
120 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, ve rtexStride,
121 indexBuffer, kVertsPerAAFillRect, kIndicesP erAAFillRect,
122 instanceCount);
123 if (!vertices || !indexBuffer) {
124 SkDebugf("Could not allocate vertices\n");
125 return;
126 }
127
128 for (int i = 0; i < instanceCount; i++) {
129 const Geometry& args = fGeoData[i];
130 this->generateAAFillRectGeometry(vertices,
131 i * kVertsPerAAFillRect * vertexStr ide,
132 vertexStride,
133 args.fColor,
134 args.fViewMatrix,
135 args.fRect,
136 args.fDevRect,
137 canTweakAlphaForCoverage);
138 }
139
140 helper.issueDraw(batchTarget);
141 }
142
143 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
144
145 private:
146 AAFillRectBatch(const Geometry& geometry) {
147 this->initClassID<AAFillRectBatch>();
148 fGeoData.push_back(geometry);
149
150 this->setBounds(geometry.fDevRect);
151 }
152
153 static const int kNumAAFillRectsInIndexBuffer = 256;
154 static const int kVertsPerAAFillRect = 8;
155 static const int kIndicesPerAAFillRect = 30;
156
157 const GrIndexBuffer* getIndexBuffer(GrResourceProvider* resourceProvider) {
158 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
159
160 static const uint16_t gFillAARectIdx[] = {
161 0, 1, 5, 5, 4, 0,
162 1, 2, 6, 6, 5, 1,
163 2, 3, 7, 7, 6, 2,
164 3, 0, 4, 4, 7, 3,
165 4, 5, 6, 6, 7, 4,
166 };
167 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect );
168 return resourceProvider->findOrCreateInstancedIndexBuffer(gFillAARectIdx ,
169 kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFill Rect,
170 gAAFillRectIndexBufferKey);
171 }
172
173 GrColor color() const { return fBatch.fColor; }
174 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
175 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover age; }
176 bool colorIgnored() const { return fBatch.fColorIgnored; }
177 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
178 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
179
180 bool onCombineIfPossible(GrBatch* t) override {
181 if (!this->pipeline()->isEqual(*t->pipeline())) {
182 return false;
183 }
184
185 AAFillRectBatch* that = t->cast<AAFillRectBatch>();
186
187 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
188 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses
189 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix
190 // using vertex attributes in these cases, but haven't investigated that
191 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
192 return false;
193 }
194
195 if (this->color() != that->color()) {
196 fBatch.fColor = GrColor_ILLEGAL;
197 }
198
199 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to
200 // not tweaking
201 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) {
202 fBatch.fCanTweakAlphaForCoverage = false;
203 }
204
205 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
206 this->joinBounds(that->bounds());
207 return true;
208 }
209
210 void generateAAFillRectGeometry(void* vertices,
211 size_t offset,
212 size_t vertexStride,
213 GrColor color,
214 const SkMatrix& viewMatrix,
215 const SkRect& rect,
216 const SkRect& devRect,
217 bool tweakAlphaForCoverage) const {
218 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset;
219
220 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
221 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride);
222
223 SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1);
224 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
225
226 if (viewMatrix.rectStaysRect()) {
227 set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_Sc alarHalf);
228 set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset);
229 } else {
230 // compute transformed (1, 0) and (0, 1) vectors
231 SkVector vec[2] = {
232 { viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY] },
233 { viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY] }
234 };
235
236 vec[0].normalize();
237 vec[0].scale(SK_ScalarHalf);
238 vec[1].normalize();
239 vec[1].scale(SK_ScalarHalf);
240
241 // create the rotated rect
242 fan0Pos->setRectFan(rect.fLeft, rect.fTop,
243 rect.fRight, rect.fBottom, vertexStride);
244 viewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4);
245
246 // Now create the inset points and then outset the original
247 // rotated points
248
249 // TL
250 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) =
251 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + v ec[1];
252 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[ 1];
253 // BL
254 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) =
255 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - v ec[1];
256 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[ 1];
257 // BR
258 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) =
259 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - v ec[1];
260 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[ 1];
261 // TR
262 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) =
263 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + v ec[1];
264 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[ 1];
265 }
266
267 // Make verts point to vertex color and then set all the color and cover age vertex attrs
268 // values.
269 verts += sizeof(SkPoint);
270 for (int i = 0; i < 4; ++i) {
271 if (tweakAlphaForCoverage) {
272 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
273 } else {
274 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
275 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0;
276 }
277 }
278
279 int scale;
280 if (inset < SK_ScalarHalf) {
281 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ;
282 SkASSERT(scale >= 0 && scale <= 255);
283 } else {
284 scale = 0xff;
285 }
286
287 verts += 4 * vertexStride;
288
289 float innerCoverage = GrNormalizeByteToFloat(scale);
290 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale );
291
292 for (int i = 0; i < 4; ++i) {
293 if (tweakAlphaForCoverage) {
294 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor;
295 } else {
296 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
297 *reinterpret_cast<float*>(verts + i * vertexStride +
298 sizeof(GrColor)) = innerCoverage;
299 }
300 }
301 }
302
303 struct BatchTracker {
304 GrColor fColor;
305 bool fUsesLocalCoords;
306 bool fColorIgnored;
307 bool fCoverageIgnored;
308 bool fCanTweakAlphaForCoverage;
309 };
310
311 BatchTracker fBatch;
312 SkSTArray<1, Geometry, true> fGeoData;
313 };
314
315 namespace {
316 // Should the coverage be multiplied into the color attrib or use a separate att rib.
317 enum CoverageAttribType {
318 kUseColor_CoverageAttribType,
319 kUseCoverage_CoverageAttribType,
320 };
321 }
322
323 void GrAARectRenderer::GeometryFillAARect(GrDrawTarget* target, 26 void GrAARectRenderer::GeometryFillAARect(GrDrawTarget* target,
324 const GrPipelineBuilder& pipelineBuild er, 27 const GrPipelineBuilder& pipelineBuild er,
325 GrColor color, 28 GrColor color,
326 const SkMatrix& viewMatrix, 29 const SkMatrix& viewMatrix,
327 const SkRect& rect, 30 const SkRect& rect,
328 const SkRect& devRect) { 31 const SkRect& devRect) {
329 AAFillRectBatch::Geometry geometry; 32 GrAAFillRectBatch::Geometry geometry;
330 geometry.fRect = rect; 33 geometry.fRect = rect;
331 geometry.fViewMatrix = viewMatrix; 34 geometry.fViewMatrix = viewMatrix;
332 geometry.fDevRect = devRect; 35 geometry.fDevRect = devRect;
333 geometry.fColor = color; 36 geometry.fColor = color;
334 37
335 38
336 SkAutoTUnref<GrBatch> batch(AAFillRectBatch::Create(geometry)); 39 SkAutoTUnref<GrBatch> batch(GrAAFillRectBatch::Create(geometry));
337 target->drawBatch(pipelineBuilder, batch); 40 target->drawBatch(pipelineBuilder, batch);
338 } 41 }
339 42
340 void GrAARectRenderer::StrokeAARect(GrDrawTarget* target, 43 void GrAARectRenderer::StrokeAARect(GrDrawTarget* target,
341 const GrPipelineBuilder& pipelineBuilder, 44 const GrPipelineBuilder& pipelineBuilder,
342 GrColor color, 45 GrColor color,
343 const SkMatrix& viewMatrix, 46 const SkMatrix& viewMatrix,
344 const SkRect& rect, 47 const SkRect& rect,
345 const SkRect& devRect, 48 const SkRect& devRect,
346 const SkStrokeRec& stroke) { 49 const SkStrokeRec& stroke) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 // edge, while vertex number of inner edge is 4, the same as miter-stroke. 95 // edge, while vertex number of inner edge is 4, the same as miter-stroke.
393 if (!miterStroke) { 96 if (!miterStroke) {
394 devOutside.inset(0, ry); 97 devOutside.inset(0, ry);
395 devOutsideAssist.outset(0, ry); 98 devOutsideAssist.outset(0, ry);
396 } 99 }
397 100
398 GeometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOutside, 101 GeometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOutside,
399 devOutsideAssist, devInside, miterStroke); 102 devOutsideAssist, devInside, miterStroke);
400 } 103 }
401 104
402 GR_DECLARE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey);
403 GR_DECLARE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey);
404
405 class AAStrokeRectBatch : public GrBatch {
406 public:
407 // TODO support AA rotated stroke rects by copying around view matrices
408 struct Geometry {
409 GrColor fColor;
410 SkRect fDevOutside;
411 SkRect fDevOutsideAssist;
412 SkRect fDevInside;
413 bool fMiterStroke;
414 };
415
416 static GrBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix) {
417 return SkNEW_ARGS(AAStrokeRectBatch, (geometry, viewMatrix));
418 }
419
420 const char* name() const override { return "AAStrokeRect"; }
421
422 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
423 // When this is called on a batch, there is only one geometry bundle
424 out->setKnownFourComponents(fGeoData[0].fColor);
425 }
426
427 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
428 out->setUnknownSingleComponent();
429 }
430
431 void initBatchTracker(const GrPipelineInfo& init) override {
432 // Handle any color overrides
433 if (!init.readsColor()) {
434 fGeoData[0].fColor = GrColor_ILLEGAL;
435 }
436 init.getOverrideColorIfSet(&fGeoData[0].fColor);
437
438 // setup batch properties
439 fBatch.fColorIgnored = !init.readsColor();
440 fBatch.fColor = fGeoData[0].fColor;
441 fBatch.fUsesLocalCoords = init.readsLocalCoords();
442 fBatch.fCoverageIgnored = !init.readsCoverage();
443 fBatch.fMiterStroke = fGeoData[0].fMiterStroke;
444 fBatch.fCanTweakAlphaForCoverage = init.canTweakAlphaForCoverage();
445 }
446
447 void generateGeometry(GrBatchTarget* batchTarget) override {
448 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
449
450 SkAutoTUnref<const GrGeometryProcessor> gp(create_fill_rect_gp(canTweakA lphaForCoverage,
451 this->vie wMatrix(),
452 this->use sLocalCoords(),
453 this->cov erageIgnored()));
454 if (!gp) {
455 SkDebugf("Couldn't create GrGeometryProcessor\n");
456 return;
457 }
458
459 batchTarget->initDraw(gp, this->pipeline());
460
461 size_t vertexStride = gp->getVertexStride();
462
463 SkASSERT(canTweakAlphaForCoverage ?
464 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) :
465 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr));
466 int innerVertexNum = 4;
467 int outerVertexNum = this->miterStroke() ? 4 : 8;
468 int verticesPerInstance = (outerVertexNum + innerVertexNum) * 2;
469 int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIn dexCnt;
470 int instanceCount = fGeoData.count();
471
472 const SkAutoTUnref<const GrIndexBuffer> indexBuffer(
473 GetIndexBuffer(batchTarget->resourceProvider(), this->miterStroke()) );
474 InstancedHelper helper;
475 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, ve rtexStride,
476 indexBuffer, verticesPerInstance, indicesP erInstance,
477 instanceCount);
478 if (!vertices || !indexBuffer) {
479 SkDebugf("Could not allocate vertices\n");
480 return;
481 }
482
483 for (int i = 0; i < instanceCount; i++) {
484 const Geometry& args = fGeoData[i];
485 this->generateAAStrokeRectGeometry(vertices,
486 i * verticesPerInstance * vertexS tride,
487 vertexStride,
488 outerVertexNum,
489 innerVertexNum,
490 args.fColor,
491 args.fDevOutside,
492 args.fDevOutsideAssist,
493 args.fDevInside,
494 args.fMiterStroke,
495 canTweakAlphaForCoverage);
496 }
497 helper.issueDraw(batchTarget);
498 }
499
500 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
501
502 private:
503 AAStrokeRectBatch(const Geometry& geometry, const SkMatrix& viewMatrix) {
504 this->initClassID<AAStrokeRectBatch>();
505 fBatch.fViewMatrix = viewMatrix;
506 fGeoData.push_back(geometry);
507
508 // If we have miterstroke then we inset devOutside and outset devOutside Assist, so we need
509 // the join for proper bounds
510 fBounds = geometry.fDevOutside;
511 fBounds.join(geometry.fDevOutsideAssist);
512 }
513
514
515 static const int kMiterIndexCnt = 3 * 24;
516 static const int kMiterVertexCnt = 16;
517 static const int kNumMiterRectsInIndexBuffer = 256;
518
519 static const int kBevelIndexCnt = 48 + 36 + 24;
520 static const int kBevelVertexCnt = 24;
521 static const int kNumBevelRectsInIndexBuffer = 256;
522
523 static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* resourceProvi der,
524 bool miterStroke) {
525
526 if (miterStroke) {
527 static const uint16_t gMiterIndices[] = {
528 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
529 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
530 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
531 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
532
533 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
534 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
535 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
536 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
537
538 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
539 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
540 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
541 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
542 };
543 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gMiterIndices) == kMiterIndexCnt);
544 GR_DEFINE_STATIC_UNIQUE_KEY(gMiterIndexBufferKey);
545 return resourceProvider->findOrCreateInstancedIndexBuffer(gMiterIndi ces,
546 kMiterIndexCnt, kNumMiterRectsInIndexBuffer, kMiterVertexCnt,
547 gMiterIndexBufferKey);
548 } else {
549 /**
550 * As in miter-stroke, index = a + b, and a is the current index, b is the shift
551 * from the first index. The index layout:
552 * outer AA line: 0~3, 4~7
553 * outer edge: 8~11, 12~15
554 * inner edge: 16~19
555 * inner AA line: 20~23
556 * Following comes a bevel-stroke rect and its indices:
557 *
558 * 4 7
559 * *********************************
560 * * ______________________________ *
561 * * / 12 15 \ *
562 * * / \ *
563 * 0 * |8 16_____________________19 11 | * 3
564 * * | | | | *
565 * * | | **************** | | *
566 * * | | * 20 23 * | | *
567 * * | | * * | | *
568 * * | | * 21 22 * | | *
569 * * | | **************** | | *
570 * * | |____________________| | *
571 * 1 * |9 17 18 10| * 2
572 * * \ / *
573 * * \13 __________________________14/ *
574 * * *
575 * **********************************
576 * 5 6
577 */
578 static const uint16_t gBevelIndices[] = {
579 // Draw outer AA, from outer AA line to outer edge, shift is 0.
580 0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0,
581 1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0,
582 5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0,
583 6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0,
584 2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0,
585 3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0,
586 7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0,
587 4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0,
588
589 // Draw the stroke, from outer edge to inner edge, shift is 8.
590 0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8,
591 1 + 8, 5 + 8, 9 + 8,
592 5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8,
593 6 + 8, 2 + 8, 10 + 8,
594 2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8,
595 3 + 8, 7 + 8, 11 + 8,
596 7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8,
597 4 + 8, 0 + 8, 8 + 8,
598
599 // Draw the inner AA, from inner edge to inner AA line, shift is 16.
600 0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16,
601 1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16,
602 2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16,
603 3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16,
604 };
605 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gBevelIndices) == kBevelIndexCnt);
606
607 GR_DEFINE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey);
608 return resourceProvider->findOrCreateInstancedIndexBuffer(gBevelIndi ces,
609 kBevelIndexCnt, kNumBevelRectsInIndexBuffer, kBevelVertexCnt,
610 gBevelIndexBufferKey);
611 }
612 }
613
614 GrColor color() const { return fBatch.fColor; }
615 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
616 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover age; }
617 bool colorIgnored() const { return fBatch.fColorIgnored; }
618 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
619 bool miterStroke() const { return fBatch.fMiterStroke; }
620 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
621
622 bool onCombineIfPossible(GrBatch* t) override {
623 if (!this->pipeline()->isEqual(*t->pipeline())) {
624 return false;
625 }
626
627 AAStrokeRectBatch* that = t->cast<AAStrokeRectBatch>();
628
629 // TODO batch across miterstroke changes
630 if (this->miterStroke() != that->miterStroke()) {
631 return false;
632 }
633
634 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses
635 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix
636 // using vertex attributes in these cases, but haven't investigated that
637 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
638 return false;
639 }
640
641 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to
642 // not tweaking
643 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) {
644 fBatch.fCanTweakAlphaForCoverage = false;
645 }
646
647 if (this->color() != that->color()) {
648 fBatch.fColor = GrColor_ILLEGAL;
649 }
650 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
651 this->joinBounds(that->bounds());
652 return true;
653 }
654
655 void generateAAStrokeRectGeometry(void* vertices,
656 size_t offset,
657 size_t vertexStride,
658 int outerVertexNum,
659 int innerVertexNum,
660 GrColor color,
661 const SkRect& devOutside,
662 const SkRect& devOutsideAssist,
663 const SkRect& devInside,
664 bool miterStroke,
665 bool tweakAlphaForCoverage) const {
666 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset;
667
668 // We create vertices for four nested rectangles. There are two ramps fr om 0 to full
669 // coverage, one on the exterior of the stroke and the other on the inte rior.
670 // The following pointers refer to the four rects, from outermost to inn ermost.
671 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
672 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * v ertexStride);
673 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vertexStride);
674 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts +
675 (2 * outerVertexNum + inne rVertexNum) *
676 vertexStride);
677
678 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
679 // TODO: this only really works if the X & Y margins are the same all ar ound
680 // the rect (or if they are all >= 1.0).
681 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.f Right);
682 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
683 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
684 if (miterStroke) {
685 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devI nside.fBottom);
686 } else {
687 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom -
688 devInside.fBottom);
689 }
690 SkASSERT(inset >= 0);
691 #else
692 SkScalar inset = SK_ScalarHalf;
693 #endif
694
695 if (miterStroke) {
696 // outermost
697 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK _ScalarHalf);
698 // inner two
699 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset);
700 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset);
701 // innermost
702 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf);
703 } else {
704 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vert exStride);
705 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts +
706 (outerVertexNum + 4) *
707 vertexStride);
708 // outermost
709 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK _ScalarHalf);
710 set_inset_fan(fan0AssistPos, vertexStride, devOutsideAssist, -SK_Sca larHalf,
711 -SK_ScalarHalf);
712 // outer one of the inner two
713 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset);
714 set_inset_fan(fan1AssistPos, vertexStride, devOutsideAssist, inset, inset);
715 // inner one of the inner two
716 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset);
717 // innermost
718 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf);
719 }
720
721 // Make verts point to vertex color and then set all the color and cover age vertex attrs
722 // values. The outermost rect has 0 coverage
723 verts += sizeof(SkPoint);
724 for (int i = 0; i < outerVertexNum; ++i) {
725 if (tweakAlphaForCoverage) {
726 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
727 } else {
728 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
729 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0;
730 }
731 }
732
733 // scale is the coverage for the the inner two rects.
734 int scale;
735 if (inset < SK_ScalarHalf) {
736 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ;
737 SkASSERT(scale >= 0 && scale <= 255);
738 } else {
739 scale = 0xff;
740 }
741
742 float innerCoverage = GrNormalizeByteToFloat(scale);
743 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale );
744
745 verts += outerVertexNum * vertexStride;
746 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
747 if (tweakAlphaForCoverage) {
748 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor;
749 } else {
750 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
751 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) =
752 innerCoverage;
753 }
754 }
755
756 // The innermost rect has 0 coverage
757 verts += (outerVertexNum + innerVertexNum) * vertexStride;
758 for (int i = 0; i < innerVertexNum; ++i) {
759 if (tweakAlphaForCoverage) {
760 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
761 } else {
762 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
763 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(Gr Color)) = 0;
764 }
765 }
766 }
767
768 struct BatchTracker {
769 SkMatrix fViewMatrix;
770 GrColor fColor;
771 bool fUsesLocalCoords;
772 bool fColorIgnored;
773 bool fCoverageIgnored;
774 bool fMiterStroke;
775 bool fCanTweakAlphaForCoverage;
776 };
777
778 BatchTracker fBatch;
779 SkSTArray<1, Geometry, true> fGeoData;
780 };
781
782 void GrAARectRenderer::GeometryStrokeAARect(GrDrawTarget* target, 105 void GrAARectRenderer::GeometryStrokeAARect(GrDrawTarget* target,
783 const GrPipelineBuilder& pipelineBui lder, 106 const GrPipelineBuilder& pipelineBui lder,
784 GrColor color, 107 GrColor color,
785 const SkMatrix& viewMatrix, 108 const SkMatrix& viewMatrix,
786 const SkRect& devOutside, 109 const SkRect& devOutside,
787 const SkRect& devOutsideAssist, 110 const SkRect& devOutsideAssist,
788 const SkRect& devInside, 111 const SkRect& devInside,
789 bool miterStroke) { 112 bool miterStroke) {
790 AAStrokeRectBatch::Geometry geometry; 113 GrAAStrokeRectBatch::Geometry geometry;
791 geometry.fColor = color; 114 geometry.fColor = color;
792 geometry.fDevOutside = devOutside; 115 geometry.fDevOutside = devOutside;
793 geometry.fDevOutsideAssist = devOutsideAssist; 116 geometry.fDevOutsideAssist = devOutsideAssist;
794 geometry.fDevInside = devInside; 117 geometry.fDevInside = devInside;
795 geometry.fMiterStroke = miterStroke; 118 geometry.fMiterStroke = miterStroke;
796 119
797 SkAutoTUnref<GrBatch> batch(AAStrokeRectBatch::Create(geometry, viewMatrix)) ; 120 SkAutoTUnref<GrBatch> batch(GrAAStrokeRectBatch::Create(geometry, viewMatrix ));
798 target->drawBatch(pipelineBuilder, batch); 121 target->drawBatch(pipelineBuilder, batch);
799 } 122 }
800 123
801 void GrAARectRenderer::FillAANestedRects(GrDrawTarget* target, 124 void GrAARectRenderer::FillAANestedRects(GrDrawTarget* target,
802 const GrPipelineBuilder& pipelineBuilde r, 125 const GrPipelineBuilder& pipelineBuilde r,
803 GrColor color, 126 GrColor color,
804 const SkMatrix& viewMatrix, 127 const SkMatrix& viewMatrix,
805 const SkRect rects[2]) { 128 const SkRect rects[2]) {
806 SkASSERT(viewMatrix.rectStaysRect()); 129 SkASSERT(viewMatrix.rectStaysRect());
807 SkASSERT(!rects[0].isEmpty() && !rects[1].isEmpty()); 130 SkASSERT(!rects[0].isEmpty() && !rects[1].isEmpty());
808 131
809 SkRect devOutside, devInside; 132 SkRect devOutside, devInside;
810 viewMatrix.mapRect(&devOutside, rects[0]); 133 viewMatrix.mapRect(&devOutside, rects[0]);
811 viewMatrix.mapRect(&devInside, rects[1]); 134 viewMatrix.mapRect(&devInside, rects[1]);
812 135
813 if (devInside.isEmpty()) { 136 if (devInside.isEmpty()) {
814 FillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, devOu tside); 137 FillAARect(target, pipelineBuilder, color, viewMatrix, devOutside, devOu tside);
815 return; 138 return;
816 } 139 }
817 140
818 GeometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOutside, 141 GeometryStrokeAARect(target, pipelineBuilder, color, viewMatrix, devOutside,
819 devOutside, devInside, true); 142 devOutside, devInside, true);
820 } 143 }
821
822 //////////////////////////////////////////////////////////////////////////////// ///////////////////
823
824 #ifdef GR_TEST_UTILS
825
826 BATCH_TEST_DEFINE(AAFillRectBatch) {
827 AAFillRectBatch::Geometry geo;
828 geo.fColor = GrRandomColor(random);
829 geo.fViewMatrix = GrTest::TestMatrix(random);
830 geo.fRect = GrTest::TestRect(random);
831 geo.fDevRect = GrTest::TestRect(random);
832 return AAFillRectBatch::Create(geo);
833 }
834
835 BATCH_TEST_DEFINE(AAStrokeRectBatch) {
836 bool miterStroke = random->nextBool();
837
838 // Create mock stroke rect
839 SkRect outside = GrTest::TestRect(random);
840 SkScalar minDim = SkMinScalar(outside.width(), outside.height());
841 SkScalar strokeWidth = minDim * 0.1f;
842 SkRect outsideAssist = outside;
843 outsideAssist.outset(strokeWidth, strokeWidth);
844 SkRect inside = outside;
845 inside.inset(strokeWidth, strokeWidth);
846
847 AAStrokeRectBatch::Geometry geo;
848 geo.fColor = GrRandomColor(random);
849 geo.fDevOutside = outside;
850 geo.fDevOutsideAssist = outsideAssist;
851 geo.fDevInside = inside;
852 geo.fMiterStroke = miterStroke;
853
854 return AAStrokeRectBatch::Create(geo, GrTest::TestMatrix(random));
855 }
856
857 #endif
OLDNEW
« no previous file with comments | « gyp/gpu.gypi ('k') | src/gpu/batches/GrAAFillRectBatch.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698