blob: c9eeed3075f9a4488db92793b6b32c4144b80798 [file] [log] [blame]
joshualitt9ff64252015-08-10 09:03:51 -07001/*
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 "GrAAFillRectBatch.h"
9
joshualitt37eb1842015-08-12 06:36:57 -070010#include "GrBatch.h"
11#include "GrColor.h"
joshualitt9ff64252015-08-10 09:03:51 -070012#include "GrDefaultGeoProcFactory.h"
13#include "GrResourceKey.h"
14#include "GrResourceProvider.h"
joshualitt37eb1842015-08-12 06:36:57 -070015#include "GrTypes.h"
16#include "SkMatrix.h"
17#include "SkRect.h"
joshualitt9ff64252015-08-10 09:03:51 -070018
19GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
20
21static void set_inset_fan(SkPoint* pts, size_t stride,
22 const SkRect& r, SkScalar dx, SkScalar dy) {
23 pts->setRectFan(r.fLeft + dx, r.fTop + dy,
24 r.fRight - dx, r.fBottom - dy, stride);
25}
26
joshualitt147dc062015-08-12 11:51:46 -070027/*
28 * AAFillRectBatch is templated to optionally allow the insertion of an additional
29 * attribute for explicit local coordinates.
30 * To use this template, an implementation must define the following static functions:
31 * A Geometry struct
32 *
33 * bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& theirs,
34 * bool usesLocalCoords)
35 *
36 * GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType()
37 *
38 * bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCoverage,
39 * bool usesLocalCoords)
40 *
41 * void FillInAttributes(intptr_t startVertex, size_t vertexStride,
42 * SkPoint* fan0Position, const Geometry&)
43 */
44template <typename Base>
joshualitt37eb1842015-08-12 06:36:57 -070045class AAFillRectBatch : public GrBatch {
46public:
joshualitt147dc062015-08-12 11:51:46 -070047 typedef typename Base::Geometry Geometry;
joshualitt9ff64252015-08-10 09:03:51 -070048
joshualitt147dc062015-08-12 11:51:46 -070049 static AAFillRectBatch* Create() {
50 return SkNEW(AAFillRectBatch);
joshualitt9ff64252015-08-10 09:03:51 -070051 }
52
joshualitt37eb1842015-08-12 06:36:57 -070053 const char* name() const override { return "AAFillRectBatch"; }
joshualitt9ff64252015-08-10 09:03:51 -070054
joshualitt37eb1842015-08-12 06:36:57 -070055 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
56 // When this is called on a batch, there is only one geometry bundle
57 out->setKnownFourComponents(fGeoData[0].fColor);
joshualitt9ff64252015-08-10 09:03:51 -070058 }
59
joshualitt37eb1842015-08-12 06:36:57 -070060 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
61 out->setUnknownSingleComponent();
joshualitt9ff64252015-08-10 09:03:51 -070062 }
63
joshualitt37eb1842015-08-12 06:36:57 -070064 void initBatchTracker(const GrPipelineOptimizations& opt) override {
65 // Handle any color overrides
66 if (!opt.readsColor()) {
67 fGeoData[0].fColor = GrColor_ILLEGAL;
68 }
69 opt.getOverrideColorIfSet(&fGeoData[0].fColor);
70
71 // setup batch properties
72 fBatch.fColorIgnored = !opt.readsColor();
73 fBatch.fColor = fGeoData[0].fColor;
74 fBatch.fUsesLocalCoords = opt.readsLocalCoords();
75 fBatch.fCoverageIgnored = !opt.readsCoverage();
76 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage();
joshualitt9ff64252015-08-10 09:03:51 -070077 }
78
joshualitt37eb1842015-08-12 06:36:57 -070079 void generateGeometry(GrBatchTarget* batchTarget) override {
80 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
joshualitt9ff64252015-08-10 09:03:51 -070081
joshualitt147dc062015-08-12 11:51:46 -070082 SkAutoTUnref<const GrGeometryProcessor> gp(CreateFillRectGP(canTweakAlphaForCoverage,
83 this->viewMatrix(),
84 this->usesLocalCoords(),
85 Base::LocalCoordsType(),
86 this->coverageIgnored()));
joshualitt37eb1842015-08-12 06:36:57 -070087 if (!gp) {
88 SkDebugf("Couldn't create GrGeometryProcessor\n");
89 return;
90 }
joshualitt9ff64252015-08-10 09:03:51 -070091
joshualitt37eb1842015-08-12 06:36:57 -070092 batchTarget->initDraw(gp, this->pipeline());
joshualitt9ff64252015-08-10 09:03:51 -070093
joshualitt37eb1842015-08-12 06:36:57 -070094 size_t vertexStride = gp->getVertexStride();
joshualitt147dc062015-08-12 11:51:46 -070095 SkASSERT(Base::StrideCheck(vertexStride, canTweakAlphaForCoverage,
96 this->usesLocalCoords()));
joshualitt37eb1842015-08-12 06:36:57 -070097 int instanceCount = fGeoData.count();
joshualitt9ff64252015-08-10 09:03:51 -070098
joshualitt37eb1842015-08-12 06:36:57 -070099 SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer(
100 batchTarget->resourceProvider()));
101 InstancedHelper helper;
102 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, vertexStride,
103 indexBuffer, kVertsPerAAFillRect, kIndicesPerAAFillRect,
104 instanceCount);
105 if (!vertices || !indexBuffer) {
106 SkDebugf("Could not allocate vertices\n");
107 return;
108 }
109
110 for (int i = 0; i < instanceCount; i++) {
joshualitt37eb1842015-08-12 06:36:57 -0700111 this->generateAAFillRectGeometry(vertices,
112 i * kVertsPerAAFillRect * vertexStride,
113 vertexStride,
joshualitt147dc062015-08-12 11:51:46 -0700114 fGeoData[i],
joshualitt37eb1842015-08-12 06:36:57 -0700115 canTweakAlphaForCoverage);
116 }
joshualitt37eb1842015-08-12 06:36:57 -0700117 helper.issueDraw(batchTarget);
118 }
119
120 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
121
joshualitt147dc062015-08-12 11:51:46 -0700122 // to avoid even the initial copy of the struct, we have a getter for the first item which
123 // is used to seed the batch with its initial geometry. After seeding, the client should call
124 // init() so the Batch can initialize itself
125 Geometry* geometry() { return &fGeoData[0]; }
126 void init() {
127 const Geometry& geo = fGeoData[0];
128 this->setBounds(geo.fDevRect);
129 }
joshualitt37eb1842015-08-12 06:36:57 -0700130
joshualitt147dc062015-08-12 11:51:46 -0700131
132private:
133 AAFillRectBatch() {
134 this->initClassID<AAFillRectBatch<Base>>();
135
136 // Push back an initial geometry
137 fGeoData.push_back();
joshualitt37eb1842015-08-12 06:36:57 -0700138 }
139
140 static const int kNumAAFillRectsInIndexBuffer = 256;
141 static const int kVertsPerAAFillRect = 8;
142 static const int kIndicesPerAAFillRect = 30;
143
144 const GrIndexBuffer* getIndexBuffer(GrResourceProvider* resourceProvider) {
145 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
146
147 static const uint16_t gFillAARectIdx[] = {
148 0, 1, 5, 5, 4, 0,
149 1, 2, 6, 6, 5, 1,
150 2, 3, 7, 7, 6, 2,
151 3, 0, 4, 4, 7, 3,
152 4, 5, 6, 6, 7, 4,
joshualitt9ff64252015-08-10 09:03:51 -0700153 };
joshualitt37eb1842015-08-12 06:36:57 -0700154 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect);
155 return resourceProvider->findOrCreateInstancedIndexBuffer(gFillAARectIdx,
156 kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect,
157 gAAFillRectIndexBufferKey);
joshualitt9ff64252015-08-10 09:03:51 -0700158 }
159
joshualitt37eb1842015-08-12 06:36:57 -0700160 GrColor color() const { return fBatch.fColor; }
161 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
162 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
163 bool colorIgnored() const { return fBatch.fColorIgnored; }
164 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
165 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
166
bsalomonc3021ed2015-08-12 11:28:11 -0700167 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
bsalomoncb02b382015-08-12 11:14:50 -0700168 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *t->pipeline(), t->bounds(),
169 caps)) {
joshualitt37eb1842015-08-12 06:36:57 -0700170 return false;
171 }
172
173 AAFillRectBatch* that = t->cast<AAFillRectBatch>();
joshualitt147dc062015-08-12 11:51:46 -0700174 if (!Base::CanCombineLocalCoords(this->viewMatrix(), that->viewMatrix(),
175 this->usesLocalCoords())) {
joshualitt37eb1842015-08-12 06:36:57 -0700176 return false;
177 }
178
179 if (this->color() != that->color()) {
180 fBatch.fColor = GrColor_ILLEGAL;
181 }
182
183 // In the event of two batches, one who can tweak, one who cannot, we just fall back to
184 // not tweaking
185 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) {
186 fBatch.fCanTweakAlphaForCoverage = false;
187 }
188
189 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
190 this->joinBounds(that->bounds());
191 return true;
192 }
193
194 void generateAAFillRectGeometry(void* vertices,
195 size_t offset,
196 size_t vertexStride,
joshualitt147dc062015-08-12 11:51:46 -0700197 const Geometry& args,
joshualitt37eb1842015-08-12 06:36:57 -0700198 bool tweakAlphaForCoverage) const {
199 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset;
200
201 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
202 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride);
203
joshualitt147dc062015-08-12 11:51:46 -0700204 SkScalar inset = SkMinScalar(args.fDevRect.width(), SK_Scalar1);
205 inset = SK_ScalarHalf * SkMinScalar(inset, args.fDevRect.height());
joshualitt37eb1842015-08-12 06:36:57 -0700206
joshualitt147dc062015-08-12 11:51:46 -0700207 if (args.fViewMatrix.rectStaysRect()) {
208 set_inset_fan(fan0Pos, vertexStride, args.fDevRect, -SK_ScalarHalf, -SK_ScalarHalf);
209 set_inset_fan(fan1Pos, vertexStride, args.fDevRect, inset, inset);
joshualitt9ff64252015-08-10 09:03:51 -0700210 } else {
joshualitt37eb1842015-08-12 06:36:57 -0700211 // compute transformed (1, 0) and (0, 1) vectors
212 SkVector vec[2] = {
joshualitt147dc062015-08-12 11:51:46 -0700213 { args.fViewMatrix[SkMatrix::kMScaleX], args.fViewMatrix[SkMatrix::kMSkewY] },
214 { args.fViewMatrix[SkMatrix::kMSkewX], args.fViewMatrix[SkMatrix::kMScaleY] }
joshualitt37eb1842015-08-12 06:36:57 -0700215 };
216
217 vec[0].normalize();
218 vec[0].scale(SK_ScalarHalf);
219 vec[1].normalize();
220 vec[1].scale(SK_ScalarHalf);
221
222 // create the rotated rect
joshualitt147dc062015-08-12 11:51:46 -0700223 fan0Pos->setRectFan(args.fRect.fLeft, args.fRect.fTop,
224 args.fRect.fRight, args.fRect.fBottom, vertexStride);
225 args.fViewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4);
joshualitt37eb1842015-08-12 06:36:57 -0700226
227 // Now create the inset points and then outset the original
228 // rotated points
229
230 // TL
231 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) =
232 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1];
233 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1];
234 // BL
235 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) =
236 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1];
237 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1];
238 // BR
239 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) =
240 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1];
241 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1];
242 // TR
243 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) =
244 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1];
245 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1];
246 }
247
joshualitt147dc062015-08-12 11:51:46 -0700248 Base::FillInAttributes(verts, vertexStride, fan0Pos, args);
249
joshualitt37eb1842015-08-12 06:36:57 -0700250 // Make verts point to vertex color and then set all the color and coverage vertex attrs
251 // values.
252 verts += sizeof(SkPoint);
253 for (int i = 0; i < 4; ++i) {
254 if (tweakAlphaForCoverage) {
255 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
256 } else {
joshualitt147dc062015-08-12 11:51:46 -0700257 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fColor;
joshualitt37eb1842015-08-12 06:36:57 -0700258 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 0;
259 }
260 }
261
262 int scale;
263 if (inset < SK_ScalarHalf) {
264 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
265 SkASSERT(scale >= 0 && scale <= 255);
266 } else {
267 scale = 0xff;
268 }
269
270 verts += 4 * vertexStride;
271
272 float innerCoverage = GrNormalizeByteToFloat(scale);
joshualitt147dc062015-08-12 11:51:46 -0700273 GrColor scaledColor = (0xff == scale) ? args.fColor : SkAlphaMulQ(args.fColor, scale);
joshualitt37eb1842015-08-12 06:36:57 -0700274
275 for (int i = 0; i < 4; ++i) {
276 if (tweakAlphaForCoverage) {
277 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
278 } else {
joshualitt147dc062015-08-12 11:51:46 -0700279 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fColor;
joshualitt37eb1842015-08-12 06:36:57 -0700280 *reinterpret_cast<float*>(verts + i * vertexStride +
281 sizeof(GrColor)) = innerCoverage;
282 }
joshualitt9ff64252015-08-10 09:03:51 -0700283 }
284 }
285
joshualitt147dc062015-08-12 11:51:46 -0700286 static const GrGeometryProcessor* CreateFillRectGP(
287 bool tweakAlphaForCoverage,
288 const SkMatrix& viewMatrix,
289 bool usesLocalCoords,
290 GrDefaultGeoProcFactory::LocalCoords::Type localCoordsType,
291 bool coverageIgnored) {
292 using namespace GrDefaultGeoProcFactory;
293
294 Color color(Color::kAttribute_Type);
295 Coverage::Type coverageType;
296 // TODO remove coverage if coverage is ignored
297 /*if (coverageIgnored) {
298 coverageType = Coverage::kNone_Type;
299 } else*/ if (tweakAlphaForCoverage) {
300 coverageType = Coverage::kSolid_Type;
301 } else {
302 coverageType = Coverage::kAttribute_Type;
303 }
304 Coverage coverage(coverageType);
305
306 // We assume the caller has inverted the viewmatrix
307 LocalCoords localCoords(usesLocalCoords ? localCoordsType : LocalCoords::kUnused_Type);
308 if (LocalCoords::kHasExplicit_Type == localCoordsType) {
309 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I());
310 } else {
311 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix);
312 }
313 }
314
joshualitt37eb1842015-08-12 06:36:57 -0700315 struct BatchTracker {
316 GrColor fColor;
317 bool fUsesLocalCoords;
318 bool fColorIgnored;
319 bool fCoverageIgnored;
320 bool fCanTweakAlphaForCoverage;
321 };
joshualitt9ff64252015-08-10 09:03:51 -0700322
joshualitt37eb1842015-08-12 06:36:57 -0700323 BatchTracker fBatch;
324 SkSTArray<1, Geometry, true> fGeoData;
325};
joshualitt9ff64252015-08-10 09:03:51 -0700326
joshualitt147dc062015-08-12 11:51:46 -0700327class AAFillRectBatchNoLocalMatrixImp {
328public:
329 struct Geometry {
330 SkMatrix fViewMatrix;
331 SkRect fRect;
332 SkRect fDevRect;
333 GrColor fColor;
334 };
335
336 inline static bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& theirs,
337 bool usesLocalCoords) {
338 // We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses
339 // local coords then we won't be able to batch. We could actually upload the viewmatrix
340 // using vertex attributes in these cases, but haven't investigated that
341 return !usesLocalCoords || mine.cheapEqualTo(theirs);
342 }
343
344 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() {
345 return GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type;
346 }
347
348 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCoverage,
349 bool usesLocalCoords) {
350 return canTweakAlphaForCoverage ?
351 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
352 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr);
353 }
354
355 inline static void FillInAttributes(intptr_t, size_t, SkPoint*, const Geometry&) {}
356};
357
358class AAFillRectBatchLocalMatrixImp {
359public:
360 struct Geometry {
361 SkMatrix fViewMatrix;
362 SkMatrix fLocalMatrix;
363 SkRect fRect;
364 SkRect fDevRect;
365 GrColor fColor;
366 };
367
368 inline static bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& theirs,
369 bool usesLocalCoords) {
370 return true;
371 }
372
373 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() {
374 return GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type;
375 }
376
377 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCoverage,
378 bool usesLocalCoords) {
379 // Whomever created us should not have done so if there are no local coords
380 SkASSERT(usesLocalCoords);
381 return canTweakAlphaForCoverage ?
382 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
383 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordCoverage);
384 }
385
386 inline static void FillInAttributes(intptr_t vertices, size_t vertexStride,
387 SkPoint* fan0Pos, const Geometry& args) {
388 SkMatrix invViewMatrix;
389 if (!args.fViewMatrix.invert(&invViewMatrix)) {
390 SkASSERT(false);
391 invViewMatrix = SkMatrix::I();
392 }
393 SkMatrix localCoordMatrix;
394 localCoordMatrix.setConcat(args.fLocalMatrix, invViewMatrix);
395 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(vertices + vertexStride - sizeof(SkPoint));
396 localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8);
397 }
398};
399
400typedef AAFillRectBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalMatrix;
401typedef AAFillRectBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatrix;
402
joshualitt37eb1842015-08-12 06:36:57 -0700403namespace GrAAFillRectBatch {
joshualitt9ff64252015-08-10 09:03:51 -0700404
joshualitt37eb1842015-08-12 06:36:57 -0700405GrBatch* Create(GrColor color,
406 const SkMatrix& viewMatrix,
407 const SkRect& rect,
408 const SkRect& devRect) {
joshualitt147dc062015-08-12 11:51:46 -0700409 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create();
410 AAFillRectBatchNoLocalMatrix::Geometry& geo = *batch->geometry();
411 geo.fColor = color;
412 geo.fViewMatrix = viewMatrix;
413 geo.fRect = rect;
414 geo.fDevRect = devRect;
415 batch->init();
416 return batch;
417}
418
419GrBatch* Create(GrColor color,
420 const SkMatrix& viewMatrix,
421 const SkMatrix& localMatrix,
422 const SkRect& rect,
423 const SkRect& devRect) {
424 AAFillRectBatchLocalMatrix* batch = AAFillRectBatchLocalMatrix::Create();
425 AAFillRectBatchLocalMatrix::Geometry& geo = *batch->geometry();
426 geo.fColor = color;
427 geo.fViewMatrix = viewMatrix;
428 geo.fLocalMatrix = localMatrix;
429 geo.fRect = rect;
430 geo.fDevRect = devRect;
431 batch->init();
432 return batch;
joshualitt9ff64252015-08-10 09:03:51 -0700433}
434
joshualitt37eb1842015-08-12 06:36:57 -0700435};
436
joshualitt9ff64252015-08-10 09:03:51 -0700437///////////////////////////////////////////////////////////////////////////////////////////////////
438
439#ifdef GR_TEST_UTILS
440
441#include "GrBatchTest.h"
442
443BATCH_TEST_DEFINE(AAFillRectBatch) {
joshualitt147dc062015-08-12 11:51:46 -0700444 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create();
445 AAFillRectBatchNoLocalMatrix::Geometry& geo = *batch->geometry();
446 geo.fColor = GrRandomColor(random);
447 geo.fViewMatrix = GrTest::TestMatrix(random);
448 geo.fRect = GrTest::TestRect(random);
449 geo.fDevRect = GrTest::TestRect(random);
450 batch->init();
451 return batch;
452}
453
454BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) {
455 AAFillRectBatchLocalMatrix* batch = AAFillRectBatchLocalMatrix::Create();
456 AAFillRectBatchLocalMatrix::Geometry& geo = *batch->geometry();
457 geo.fColor = GrRandomColor(random);
458 geo.fViewMatrix = GrTest::TestMatrix(random);
459 geo.fLocalMatrix = GrTest::TestMatrix(random);
460 geo.fRect = GrTest::TestRect(random);
461 geo.fDevRect = GrTest::TestRect(random);
462 batch->init();
463 return batch;
joshualitt9ff64252015-08-10 09:03:51 -0700464}
465
466#endif