blob: 4cea65ac56451dd309d068a3ebb01b6cad305989 [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
joshualitt27801bf2015-08-12 12:52:47 -070027static const int kNumAAFillRectsInIndexBuffer = 256;
28static const int kVertsPerAAFillRect = 8;
29static const int kIndicesPerAAFillRect = 30;
30
31const GrIndexBuffer* get_index_buffer(GrResourceProvider* resourceProvider) {
32 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
33
34 static const uint16_t gFillAARectIdx[] = {
35 0, 1, 5, 5, 4, 0,
36 1, 2, 6, 6, 5, 1,
37 2, 3, 7, 7, 6, 2,
38 3, 0, 4, 4, 7, 3,
39 4, 5, 6, 6, 7, 4,
40 };
41 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect);
42 return resourceProvider->findOrCreateInstancedIndexBuffer(gFillAARectIdx,
43 kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect,
44 gAAFillRectIndexBufferKey);
45}
46
joshualitt147dc062015-08-12 11:51:46 -070047/*
48 * AAFillRectBatch is templated to optionally allow the insertion of an additional
49 * attribute for explicit local coordinates.
50 * To use this template, an implementation must define the following static functions:
51 * A Geometry struct
52 *
53 * bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& theirs,
54 * bool usesLocalCoords)
55 *
56 * GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType()
57 *
58 * bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCoverage,
59 * bool usesLocalCoords)
60 *
61 * void FillInAttributes(intptr_t startVertex, size_t vertexStride,
62 * SkPoint* fan0Position, const Geometry&)
63 */
64template <typename Base>
joshualitt37eb1842015-08-12 06:36:57 -070065class AAFillRectBatch : public GrBatch {
66public:
joshualitt147dc062015-08-12 11:51:46 -070067 typedef typename Base::Geometry Geometry;
joshualitt9ff64252015-08-10 09:03:51 -070068
joshualitt147dc062015-08-12 11:51:46 -070069 static AAFillRectBatch* Create() {
70 return SkNEW(AAFillRectBatch);
joshualitt9ff64252015-08-10 09:03:51 -070071 }
72
joshualitt37eb1842015-08-12 06:36:57 -070073 const char* name() const override { return "AAFillRectBatch"; }
joshualitt9ff64252015-08-10 09:03:51 -070074
joshualitt37eb1842015-08-12 06:36:57 -070075 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
76 // When this is called on a batch, there is only one geometry bundle
77 out->setKnownFourComponents(fGeoData[0].fColor);
joshualitt9ff64252015-08-10 09:03:51 -070078 }
79
joshualitt37eb1842015-08-12 06:36:57 -070080 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
81 out->setUnknownSingleComponent();
joshualitt9ff64252015-08-10 09:03:51 -070082 }
83
joshualitt37eb1842015-08-12 06:36:57 -070084 void initBatchTracker(const GrPipelineOptimizations& opt) override {
85 // Handle any color overrides
86 if (!opt.readsColor()) {
87 fGeoData[0].fColor = GrColor_ILLEGAL;
88 }
89 opt.getOverrideColorIfSet(&fGeoData[0].fColor);
90
91 // setup batch properties
92 fBatch.fColorIgnored = !opt.readsColor();
93 fBatch.fColor = fGeoData[0].fColor;
94 fBatch.fUsesLocalCoords = opt.readsLocalCoords();
95 fBatch.fCoverageIgnored = !opt.readsCoverage();
96 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage();
joshualitt9ff64252015-08-10 09:03:51 -070097 }
98
joshualitt37eb1842015-08-12 06:36:57 -070099 void generateGeometry(GrBatchTarget* batchTarget) override {
100 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
joshualitt9ff64252015-08-10 09:03:51 -0700101
joshualitt147dc062015-08-12 11:51:46 -0700102 SkAutoTUnref<const GrGeometryProcessor> gp(CreateFillRectGP(canTweakAlphaForCoverage,
103 this->viewMatrix(),
104 this->usesLocalCoords(),
105 Base::LocalCoordsType(),
106 this->coverageIgnored()));
joshualitt37eb1842015-08-12 06:36:57 -0700107 if (!gp) {
108 SkDebugf("Couldn't create GrGeometryProcessor\n");
109 return;
110 }
joshualitt9ff64252015-08-10 09:03:51 -0700111
joshualitt37eb1842015-08-12 06:36:57 -0700112 batchTarget->initDraw(gp, this->pipeline());
joshualitt9ff64252015-08-10 09:03:51 -0700113
joshualitt37eb1842015-08-12 06:36:57 -0700114 size_t vertexStride = gp->getVertexStride();
joshualitt147dc062015-08-12 11:51:46 -0700115 SkASSERT(Base::StrideCheck(vertexStride, canTweakAlphaForCoverage,
116 this->usesLocalCoords()));
joshualitt37eb1842015-08-12 06:36:57 -0700117 int instanceCount = fGeoData.count();
joshualitt9ff64252015-08-10 09:03:51 -0700118
joshualitt27801bf2015-08-12 12:52:47 -0700119 SkAutoTUnref<const GrIndexBuffer> indexBuffer(get_index_buffer(
joshualitt37eb1842015-08-12 06:36:57 -0700120 batchTarget->resourceProvider()));
121 InstancedHelper helper;
122 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, vertexStride,
123 indexBuffer, kVertsPerAAFillRect, kIndicesPerAAFillRect,
124 instanceCount);
125 if (!vertices || !indexBuffer) {
126 SkDebugf("Could not allocate vertices\n");
127 return;
128 }
129
130 for (int i = 0; i < instanceCount; i++) {
joshualitt37eb1842015-08-12 06:36:57 -0700131 this->generateAAFillRectGeometry(vertices,
132 i * kVertsPerAAFillRect * vertexStride,
133 vertexStride,
joshualitt147dc062015-08-12 11:51:46 -0700134 fGeoData[i],
joshualitt37eb1842015-08-12 06:36:57 -0700135 canTweakAlphaForCoverage);
136 }
joshualitt37eb1842015-08-12 06:36:57 -0700137 helper.issueDraw(batchTarget);
138 }
139
140 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
141
joshualitt147dc062015-08-12 11:51:46 -0700142 // to avoid even the initial copy of the struct, we have a getter for the first item which
143 // is used to seed the batch with its initial geometry. After seeding, the client should call
144 // init() so the Batch can initialize itself
145 Geometry* geometry() { return &fGeoData[0]; }
146 void init() {
147 const Geometry& geo = fGeoData[0];
148 this->setBounds(geo.fDevRect);
149 }
joshualitt37eb1842015-08-12 06:36:57 -0700150
joshualitt147dc062015-08-12 11:51:46 -0700151
152private:
153 AAFillRectBatch() {
154 this->initClassID<AAFillRectBatch<Base>>();
155
156 // Push back an initial geometry
157 fGeoData.push_back();
joshualitt37eb1842015-08-12 06:36:57 -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
joshualitt272b7482015-08-13 07:12:50 -0700223 fan0Pos->setRectFan(args.fDevRect.fLeft, args.fDevRect.fTop,
224 args.fDevRect.fRight, args.fDevRect.fBottom, vertexStride);
joshualitt37eb1842015-08-12 06:36:57 -0700225
226 // Now create the inset points and then outset the original
227 // rotated points
228
229 // TL
230 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) =
231 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1];
232 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1];
233 // BL
234 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) =
235 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1];
236 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1];
237 // BR
238 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) =
239 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1];
240 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1];
241 // TR
242 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) =
243 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1];
244 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1];
245 }
246
joshualitt147dc062015-08-12 11:51:46 -0700247 Base::FillInAttributes(verts, vertexStride, fan0Pos, args);
248
joshualitt37eb1842015-08-12 06:36:57 -0700249 // Make verts point to vertex color and then set all the color and coverage vertex attrs
250 // values.
251 verts += sizeof(SkPoint);
252 for (int i = 0; i < 4; ++i) {
253 if (tweakAlphaForCoverage) {
254 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
255 } else {
joshualitt147dc062015-08-12 11:51:46 -0700256 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fColor;
joshualitt37eb1842015-08-12 06:36:57 -0700257 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 0;
258 }
259 }
260
261 int scale;
262 if (inset < SK_ScalarHalf) {
263 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
264 SkASSERT(scale >= 0 && scale <= 255);
265 } else {
266 scale = 0xff;
267 }
268
269 verts += 4 * vertexStride;
270
271 float innerCoverage = GrNormalizeByteToFloat(scale);
joshualitt147dc062015-08-12 11:51:46 -0700272 GrColor scaledColor = (0xff == scale) ? args.fColor : SkAlphaMulQ(args.fColor, scale);
joshualitt37eb1842015-08-12 06:36:57 -0700273
274 for (int i = 0; i < 4; ++i) {
275 if (tweakAlphaForCoverage) {
276 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
277 } else {
joshualitt147dc062015-08-12 11:51:46 -0700278 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fColor;
joshualitt37eb1842015-08-12 06:36:57 -0700279 *reinterpret_cast<float*>(verts + i * vertexStride +
280 sizeof(GrColor)) = innerCoverage;
281 }
joshualitt9ff64252015-08-10 09:03:51 -0700282 }
283 }
284
joshualitt147dc062015-08-12 11:51:46 -0700285 static const GrGeometryProcessor* CreateFillRectGP(
286 bool tweakAlphaForCoverage,
287 const SkMatrix& viewMatrix,
288 bool usesLocalCoords,
289 GrDefaultGeoProcFactory::LocalCoords::Type localCoordsType,
290 bool coverageIgnored) {
291 using namespace GrDefaultGeoProcFactory;
292
293 Color color(Color::kAttribute_Type);
294 Coverage::Type coverageType;
295 // TODO remove coverage if coverage is ignored
296 /*if (coverageIgnored) {
297 coverageType = Coverage::kNone_Type;
298 } else*/ if (tweakAlphaForCoverage) {
299 coverageType = Coverage::kSolid_Type;
300 } else {
301 coverageType = Coverage::kAttribute_Type;
302 }
303 Coverage coverage(coverageType);
304
305 // We assume the caller has inverted the viewmatrix
joshualitt147dc062015-08-12 11:51:46 -0700306 if (LocalCoords::kHasExplicit_Type == localCoordsType) {
joshualitt27801bf2015-08-12 12:52:47 -0700307 LocalCoords localCoords(localCoordsType);
joshualitt147dc062015-08-12 11:51:46 -0700308 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I());
309 } else {
joshualitt27801bf2015-08-12 12:52:47 -0700310 LocalCoords localCoords(usesLocalCoords ? localCoordsType : LocalCoords::kUnused_Type);
joshualitt147dc062015-08-12 11:51:46 -0700311 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;
joshualitt147dc062015-08-12 11:51:46 -0700331 SkRect fDevRect;
332 GrColor fColor;
333 };
334
335 inline static bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& theirs,
336 bool usesLocalCoords) {
337 // We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses
338 // local coords then we won't be able to batch. We could actually upload the viewmatrix
339 // using vertex attributes in these cases, but haven't investigated that
340 return !usesLocalCoords || mine.cheapEqualTo(theirs);
341 }
342
343 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() {
344 return GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type;
345 }
346
347 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCoverage,
348 bool usesLocalCoords) {
349 return canTweakAlphaForCoverage ?
350 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
351 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr);
352 }
353
354 inline static void FillInAttributes(intptr_t, size_t, SkPoint*, const Geometry&) {}
355};
356
357class AAFillRectBatchLocalMatrixImp {
358public:
359 struct Geometry {
360 SkMatrix fViewMatrix;
361 SkMatrix fLocalMatrix;
joshualitt147dc062015-08-12 11:51:46 -0700362 SkRect fDevRect;
363 GrColor fColor;
364 };
365
366 inline static bool CanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& theirs,
367 bool usesLocalCoords) {
368 return true;
369 }
370
371 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() {
372 return GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type;
373 }
374
375 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCoverage,
376 bool usesLocalCoords) {
377 // Whomever created us should not have done so if there are no local coords
joshualitt147dc062015-08-12 11:51:46 -0700378 return canTweakAlphaForCoverage ?
379 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
380 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordCoverage);
381 }
382
383 inline static void FillInAttributes(intptr_t vertices, size_t vertexStride,
384 SkPoint* fan0Pos, const Geometry& args) {
385 SkMatrix invViewMatrix;
386 if (!args.fViewMatrix.invert(&invViewMatrix)) {
387 SkASSERT(false);
388 invViewMatrix = SkMatrix::I();
389 }
390 SkMatrix localCoordMatrix;
391 localCoordMatrix.setConcat(args.fLocalMatrix, invViewMatrix);
392 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(vertices + vertexStride - sizeof(SkPoint));
393 localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8);
394 }
395};
396
397typedef AAFillRectBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalMatrix;
398typedef AAFillRectBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatrix;
399
joshualitt37eb1842015-08-12 06:36:57 -0700400namespace GrAAFillRectBatch {
joshualitt9ff64252015-08-10 09:03:51 -0700401
joshualitt37eb1842015-08-12 06:36:57 -0700402GrBatch* Create(GrColor color,
403 const SkMatrix& viewMatrix,
404 const SkRect& rect,
405 const SkRect& devRect) {
joshualitt147dc062015-08-12 11:51:46 -0700406 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create();
407 AAFillRectBatchNoLocalMatrix::Geometry& geo = *batch->geometry();
408 geo.fColor = color;
409 geo.fViewMatrix = viewMatrix;
joshualitt147dc062015-08-12 11:51:46 -0700410 geo.fDevRect = devRect;
411 batch->init();
412 return batch;
413}
414
415GrBatch* Create(GrColor color,
416 const SkMatrix& viewMatrix,
417 const SkMatrix& localMatrix,
418 const SkRect& rect,
419 const SkRect& devRect) {
420 AAFillRectBatchLocalMatrix* batch = AAFillRectBatchLocalMatrix::Create();
421 AAFillRectBatchLocalMatrix::Geometry& geo = *batch->geometry();
422 geo.fColor = color;
423 geo.fViewMatrix = viewMatrix;
424 geo.fLocalMatrix = localMatrix;
joshualitt147dc062015-08-12 11:51:46 -0700425 geo.fDevRect = devRect;
426 batch->init();
427 return batch;
joshualitt9ff64252015-08-10 09:03:51 -0700428}
429
joshualitt37eb1842015-08-12 06:36:57 -0700430};
431
joshualitt9ff64252015-08-10 09:03:51 -0700432///////////////////////////////////////////////////////////////////////////////////////////////////
433
434#ifdef GR_TEST_UTILS
435
436#include "GrBatchTest.h"
437
438BATCH_TEST_DEFINE(AAFillRectBatch) {
joshualitt147dc062015-08-12 11:51:46 -0700439 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create();
440 AAFillRectBatchNoLocalMatrix::Geometry& geo = *batch->geometry();
441 geo.fColor = GrRandomColor(random);
442 geo.fViewMatrix = GrTest::TestMatrix(random);
joshualitt147dc062015-08-12 11:51:46 -0700443 geo.fDevRect = GrTest::TestRect(random);
444 batch->init();
445 return batch;
446}
447
448BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) {
449 AAFillRectBatchLocalMatrix* batch = AAFillRectBatchLocalMatrix::Create();
450 AAFillRectBatchLocalMatrix::Geometry& geo = *batch->geometry();
451 geo.fColor = GrRandomColor(random);
452 geo.fViewMatrix = GrTest::TestMatrix(random);
453 geo.fLocalMatrix = GrTest::TestMatrix(random);
joshualitt147dc062015-08-12 11:51:46 -0700454 geo.fDevRect = GrTest::TestRect(random);
455 batch->init();
456 return batch;
joshualitt9ff64252015-08-10 09:03:51 -0700457}
458
459#endif