blob: 890a18b57638ef3fb41b6c6b6028139790e00383 [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 "GrColor.h"
joshualitt9ff64252015-08-10 09:03:51 -070011#include "GrDefaultGeoProcFactory.h"
12#include "GrResourceKey.h"
13#include "GrResourceProvider.h"
joshualitt2ad37be2015-08-18 10:16:01 -070014#include "GrTInstanceBatch.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
cdalton397536c2016-03-25 12:15:03 -070031const GrBuffer* get_index_buffer(GrResourceProvider* resourceProvider) {
joshualitt27801bf2015-08-12 12:52:47 -070032 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
joshualittcd47b712015-08-18 07:25:38 -070047static const GrGeometryProcessor* create_fill_rect_gp(
48 const SkMatrix& viewMatrix,
ethannicholasff210322015-11-24 12:10:10 -080049 const GrXPOverridesForBatch& overrides,
joshualittcd47b712015-08-18 07:25:38 -070050 GrDefaultGeoProcFactory::LocalCoords::Type localCoordsType) {
51 using namespace GrDefaultGeoProcFactory;
52
53 Color color(Color::kAttribute_Type);
54 Coverage::Type coverageType;
55 // TODO remove coverage if coverage is ignored
56 /*if (coverageIgnored) {
57 coverageType = Coverage::kNone_Type;
ethannicholasff210322015-11-24 12:10:10 -080058 } else*/ if (overrides.canTweakAlphaForCoverage()) {
joshualittcd47b712015-08-18 07:25:38 -070059 coverageType = Coverage::kSolid_Type;
60 } else {
61 coverageType = Coverage::kAttribute_Type;
62 }
63 Coverage coverage(coverageType);
64
65 // We assume the caller has inverted the viewmatrix
66 if (LocalCoords::kHasExplicit_Type == localCoordsType) {
67 LocalCoords localCoords(localCoordsType);
68 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I());
69 } else {
ethannicholasff210322015-11-24 12:10:10 -080070 LocalCoords localCoords(overrides.readsLocalCoords() ? localCoordsType :
71 LocalCoords::kUnused_Type);
joshualittcd47b712015-08-18 07:25:38 -070072 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix);
73 }
74}
75
76static void generate_aa_fill_rect_geometry(intptr_t verts,
77 size_t vertexStride,
78 GrColor color,
79 const SkMatrix& viewMatrix,
80 const SkRect& rect,
81 const SkRect& devRect,
ethannicholasff210322015-11-24 12:10:10 -080082 const GrXPOverridesForBatch& overrides,
joshualittcd47b712015-08-18 07:25:38 -070083 const SkMatrix* localMatrix) {
84 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
85 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride);
86
87 SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1);
88 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
89
90 if (viewMatrix.rectStaysRect()) {
91 set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_ScalarHalf);
92 set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset);
93 } else {
94 // compute transformed (1, 0) and (0, 1) vectors
95 SkVector vec[2] = {
96 { viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY] },
97 { viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY] }
98 };
99
100 vec[0].normalize();
101 vec[0].scale(SK_ScalarHalf);
102 vec[1].normalize();
103 vec[1].scale(SK_ScalarHalf);
104
105 // create the rotated rect
106 fan0Pos->setRectFan(rect.fLeft, rect.fTop,
107 rect.fRight, rect.fBottom, vertexStride);
108 viewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4);
109
110 // Now create the inset points and then outset the original
111 // rotated points
112
113 // TL
114 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) =
115 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1];
116 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1];
117 // BL
118 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) =
119 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1];
120 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1];
121 // BR
122 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) =
123 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1];
124 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1];
125 // TR
126 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) =
127 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1];
128 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1];
129 }
130
131 if (localMatrix) {
132 SkMatrix invViewMatrix;
133 if (!viewMatrix.invert(&invViewMatrix)) {
134 SkASSERT(false);
135 invViewMatrix = SkMatrix::I();
136 }
137 SkMatrix localCoordMatrix;
138 localCoordMatrix.setConcat(*localMatrix, invViewMatrix);
139 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(verts + sizeof(SkPoint) + sizeof(GrColor));
140 localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8);
141 }
142
ethannicholasff210322015-11-24 12:10:10 -0800143 bool tweakAlphaForCoverage = overrides.canTweakAlphaForCoverage();
joshualittcd47b712015-08-18 07:25:38 -0700144
145 // Make verts point to vertex color and then set all the color and coverage vertex attrs
146 // values.
147 verts += sizeof(SkPoint);
148
149 // The coverage offset is always the last vertex attribute
150 intptr_t coverageOffset = vertexStride - sizeof(GrColor) - sizeof(SkPoint);
151 for (int i = 0; i < 4; ++i) {
152 if (tweakAlphaForCoverage) {
153 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
154 } else {
155 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
156 *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = 0;
157 }
158 }
159
160 int scale;
161 if (inset < SK_ScalarHalf) {
162 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
163 SkASSERT(scale >= 0 && scale <= 255);
164 } else {
165 scale = 0xff;
166 }
167
168 verts += 4 * vertexStride;
169
170 float innerCoverage = GrNormalizeByteToFloat(scale);
171 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
172
173 for (int i = 0; i < 4; ++i) {
174 if (tweakAlphaForCoverage) {
175 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
176 } else {
177 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
178 *reinterpret_cast<float*>(verts + i * vertexStride +
179 coverageOffset) = innerCoverage;
180 }
181 }
182}
183
joshualitt2ad37be2015-08-18 10:16:01 -0700184// Common functions
185class AAFillRectBatchBase {
186public:
187 static const int kVertsPerInstance = kVertsPerAAFillRect;
188 static const int kIndicesPerInstance = kIndicesPerAAFillRect;
189
joshualitt2244c272015-08-21 10:33:15 -0700190 static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
191 out->setUnknownSingleComponent();
192 }
193
cdalton397536c2016-03-25 12:15:03 -0700194 static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
joshualitt2ad37be2015-08-18 10:16:01 -0700195 return get_index_buffer(rp);
196 }
joshualitt2244c272015-08-21 10:33:15 -0700197
198 template <class Geometry>
199 static void SetBounds(const Geometry& geo, SkRect* outBounds) {
200 *outBounds = geo.fDevRect;
201 }
joshualittaa37a962015-09-18 13:03:25 -0700202
203 template <class Geometry>
204 static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
205 outBounds->join(geo.fDevRect);
206 }
joshualitt2ad37be2015-08-18 10:16:01 -0700207};
208
209class AAFillRectBatchNoLocalMatrixImp : public AAFillRectBatchBase {
joshualitt147dc062015-08-12 11:51:46 -0700210public:
211 struct Geometry {
212 SkMatrix fViewMatrix;
joshualitt40ac15a2015-08-14 08:45:39 -0700213 SkRect fRect;
joshualitt147dc062015-08-12 11:51:46 -0700214 SkRect fDevRect;
215 GrColor fColor;
216 };
217
joshualitt2244c272015-08-21 10:33:15 -0700218 static const char* Name() { return "AAFillRectBatchNoLocalMatrix"; }
joshualitt2ad37be2015-08-18 10:16:01 -0700219
robertphillips783a4da2015-11-19 14:00:02 -0800220 static SkString DumpInfo(const Geometry& geo, int index) {
robertphillipse004bfc2015-11-16 09:06:59 -0800221 SkString str;
robertphillips783a4da2015-11-19 14:00:02 -0800222 str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
223 index,
robertphillipse004bfc2015-11-16 09:06:59 -0800224 geo.fColor,
225 geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
226 return str;
227 }
228
joshualitt2244c272015-08-21 10:33:15 -0700229 static bool CanCombine(const Geometry& mine, const Geometry& theirs,
ethannicholasff210322015-11-24 12:10:10 -0800230 const GrXPOverridesForBatch& overrides) {
joshualitt147dc062015-08-12 11:51:46 -0700231 // We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses
232 // local coords then we won't be able to batch. We could actually upload the viewmatrix
233 // using vertex attributes in these cases, but haven't investigated that
ethannicholasff210322015-11-24 12:10:10 -0800234 return !overrides.readsLocalCoords() || mine.fViewMatrix.cheapEqualTo(theirs.fViewMatrix);
joshualitt147dc062015-08-12 11:51:46 -0700235 }
236
joshualitt2244c272015-08-21 10:33:15 -0700237 static const GrGeometryProcessor* CreateGP(const Geometry& geo,
ethannicholasff210322015-11-24 12:10:10 -0800238 const GrXPOverridesForBatch& overrides) {
joshualittcd47b712015-08-18 07:25:38 -0700239 const GrGeometryProcessor* gp =
ethannicholasff210322015-11-24 12:10:10 -0800240 create_fill_rect_gp(geo.fViewMatrix, overrides,
joshualittcd47b712015-08-18 07:25:38 -0700241 GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type);
242
ethannicholasff210322015-11-24 12:10:10 -0800243 SkASSERT(overrides.canTweakAlphaForCoverage() ?
joshualittcd47b712015-08-18 07:25:38 -0700244 gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
245 gp->getVertexStride() ==
246 sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
247 return gp;
joshualitt147dc062015-08-12 11:51:46 -0700248 }
249
joshualitt2244c272015-08-21 10:33:15 -0700250 static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
ethannicholasff210322015-11-24 12:10:10 -0800251 const GrXPOverridesForBatch& overrides) {
joshualittcd47b712015-08-18 07:25:38 -0700252 generate_aa_fill_rect_geometry(vertices, vertexStride,
ethannicholasff210322015-11-24 12:10:10 -0800253 geo.fColor, geo.fViewMatrix, geo.fRect, geo.fDevRect,
254 overrides, nullptr);
joshualitt147dc062015-08-12 11:51:46 -0700255 }
joshualitt147dc062015-08-12 11:51:46 -0700256};
257
joshualitt2ad37be2015-08-18 10:16:01 -0700258class AAFillRectBatchLocalMatrixImp : public AAFillRectBatchBase {
joshualitt147dc062015-08-12 11:51:46 -0700259public:
260 struct Geometry {
261 SkMatrix fViewMatrix;
262 SkMatrix fLocalMatrix;
joshualitt40ac15a2015-08-14 08:45:39 -0700263 SkRect fRect;
joshualitt147dc062015-08-12 11:51:46 -0700264 SkRect fDevRect;
265 GrColor fColor;
266 };
267
joshualitt2244c272015-08-21 10:33:15 -0700268 static const char* Name() { return "AAFillRectBatchLocalMatrix"; }
joshualitt2ad37be2015-08-18 10:16:01 -0700269
robertphillips783a4da2015-11-19 14:00:02 -0800270 static SkString DumpInfo(const Geometry& geo, int index) {
robertphillipse004bfc2015-11-16 09:06:59 -0800271 SkString str;
robertphillips783a4da2015-11-19 14:00:02 -0800272 str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
273 index,
robertphillipse004bfc2015-11-16 09:06:59 -0800274 geo.fColor,
275 geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
276 return str;
277 }
278
joshualitt2244c272015-08-21 10:33:15 -0700279 static bool CanCombine(const Geometry& mine, const Geometry& theirs,
ethannicholasff210322015-11-24 12:10:10 -0800280 const GrXPOverridesForBatch& overrides) {
joshualitt147dc062015-08-12 11:51:46 -0700281 return true;
282 }
283
joshualitt2244c272015-08-21 10:33:15 -0700284 static const GrGeometryProcessor* CreateGP(const Geometry& geo,
ethannicholasff210322015-11-24 12:10:10 -0800285 const GrXPOverridesForBatch& overrides) {
joshualittcd47b712015-08-18 07:25:38 -0700286 const GrGeometryProcessor* gp =
ethannicholasff210322015-11-24 12:10:10 -0800287 create_fill_rect_gp(geo.fViewMatrix, overrides,
joshualittcd47b712015-08-18 07:25:38 -0700288 GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type);
289
ethannicholasff210322015-11-24 12:10:10 -0800290 SkASSERT(overrides.canTweakAlphaForCoverage() ?
joshualittcd47b712015-08-18 07:25:38 -0700291 gp->getVertexStride() ==
292 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
293 gp->getVertexStride() ==
294 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordCoverage));
295 return gp;
joshualitt147dc062015-08-12 11:51:46 -0700296 }
297
joshualitt2244c272015-08-21 10:33:15 -0700298 static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
ethannicholasff210322015-11-24 12:10:10 -0800299 const GrXPOverridesForBatch& overrides) {
joshualittcd47b712015-08-18 07:25:38 -0700300 generate_aa_fill_rect_geometry(vertices, vertexStride,
ethannicholasff210322015-11-24 12:10:10 -0800301 geo.fColor, geo.fViewMatrix, geo.fRect, geo.fDevRect,
302 overrides, &geo.fLocalMatrix);
joshualitt147dc062015-08-12 11:51:46 -0700303 }
304};
305
joshualitt2ad37be2015-08-18 10:16:01 -0700306typedef GrTInstanceBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalMatrix;
307typedef GrTInstanceBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatrix;
joshualitt147dc062015-08-12 11:51:46 -0700308
joshualittaa37a962015-09-18 13:03:25 -0700309inline static void append_to_batch(AAFillRectBatchNoLocalMatrix* batch, GrColor color,
310 const SkMatrix& viewMatrix, const SkRect& rect,
311 const SkRect& devRect) {
312 AAFillRectBatchNoLocalMatrix::Geometry& geo = batch->geoData()->push_back();
313 geo.fColor = color;
314 geo.fViewMatrix = viewMatrix;
315 geo.fRect = rect;
316 geo.fDevRect = devRect;
317}
318
319inline static void append_to_batch(AAFillRectBatchLocalMatrix* batch, GrColor color,
320 const SkMatrix& viewMatrix, const SkMatrix& localMatrix,
321 const SkRect& rect, const SkRect& devRect) {
322 AAFillRectBatchLocalMatrix::Geometry& geo = batch->geoData()->push_back();
323 geo.fColor = color;
324 geo.fViewMatrix = viewMatrix;
325 geo.fLocalMatrix = localMatrix;
326 geo.fRect = rect;
327 geo.fDevRect = devRect;
328}
329
joshualitt37eb1842015-08-12 06:36:57 -0700330namespace GrAAFillRectBatch {
joshualitt9ff64252015-08-10 09:03:51 -0700331
bsalomonabd30f52015-08-13 13:34:48 -0700332GrDrawBatch* Create(GrColor color,
333 const SkMatrix& viewMatrix,
334 const SkRect& rect,
335 const SkRect& devRect) {
joshualitt147dc062015-08-12 11:51:46 -0700336 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create();
joshualittaa37a962015-09-18 13:03:25 -0700337 append_to_batch(batch, color, viewMatrix, rect, devRect);
joshualitt147dc062015-08-12 11:51:46 -0700338 batch->init();
339 return batch;
340}
341
bsalomonabd30f52015-08-13 13:34:48 -0700342GrDrawBatch* Create(GrColor color,
343 const SkMatrix& viewMatrix,
344 const SkMatrix& localMatrix,
345 const SkRect& rect,
346 const SkRect& devRect) {
joshualitt147dc062015-08-12 11:51:46 -0700347 AAFillRectBatchLocalMatrix* batch = AAFillRectBatchLocalMatrix::Create();
joshualittaa37a962015-09-18 13:03:25 -0700348 append_to_batch(batch, color, viewMatrix, localMatrix, rect, devRect);
joshualitt147dc062015-08-12 11:51:46 -0700349 batch->init();
350 return batch;
joshualitt9ff64252015-08-10 09:03:51 -0700351}
352
bsalomonc55271f2015-11-09 11:55:57 -0800353GrDrawBatch* Create(GrColor color,
354 const SkMatrix& viewMatrix,
355 const SkMatrix& localMatrix,
356 const SkRect& rect) {
357 SkRect devRect;
358 viewMatrix.mapRect(&devRect, rect);
359 return Create(color, viewMatrix, localMatrix, rect, devRect);
360}
361
362GrDrawBatch* CreateWithLocalRect(GrColor color,
363 const SkMatrix& viewMatrix,
364 const SkRect& rect,
365 const SkRect& localRect) {
366 SkRect devRect;
367 viewMatrix.mapRect(&devRect, rect);
368 SkMatrix localMatrix;
369 if (!localMatrix.setRectToRect(rect, localRect, SkMatrix::kFill_ScaleToFit)) {
370 return nullptr;
371 }
372 return Create(color, viewMatrix, localMatrix, rect, devRect);
373}
374
joshualittaa37a962015-09-18 13:03:25 -0700375void Append(GrBatch* origBatch,
376 GrColor color,
377 const SkMatrix& viewMatrix,
378 const SkRect& rect,
379 const SkRect& devRect) {
380 AAFillRectBatchNoLocalMatrix* batch = origBatch->cast<AAFillRectBatchNoLocalMatrix>();
381 append_to_batch(batch, color, viewMatrix, rect, devRect);
382 batch->updateBoundsAfterAppend();
383}
384
385void Append(GrBatch* origBatch,
386 GrColor color,
387 const SkMatrix& viewMatrix,
388 const SkMatrix& localMatrix,
389 const SkRect& rect,
390 const SkRect& devRect) {
391 AAFillRectBatchLocalMatrix* batch = origBatch->cast<AAFillRectBatchLocalMatrix>();
392 append_to_batch(batch, color, viewMatrix, localMatrix, rect, devRect);
393 batch->updateBoundsAfterAppend();
394}
395
joshualitt37eb1842015-08-12 06:36:57 -0700396};
397
joshualitt9ff64252015-08-10 09:03:51 -0700398///////////////////////////////////////////////////////////////////////////////////////////////////
399
400#ifdef GR_TEST_UTILS
401
402#include "GrBatchTest.h"
403
bsalomonabd30f52015-08-13 13:34:48 -0700404DRAW_BATCH_TEST_DEFINE(AAFillRectBatch) {
joshualitt090ae8e2015-08-14 09:01:21 -0700405 GrColor color = GrRandomColor(random);
406 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
407 SkRect rect = GrTest::TestRect(random);
408 SkRect devRect = GrTest::TestRect(random);
409 return GrAAFillRectBatch::Create(color, viewMatrix, rect, devRect);
joshualitt147dc062015-08-12 11:51:46 -0700410}
411
bsalomonabd30f52015-08-13 13:34:48 -0700412DRAW_BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) {
joshualitt090ae8e2015-08-14 09:01:21 -0700413 GrColor color = GrRandomColor(random);
414 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
415 SkMatrix localMatrix = GrTest::TestMatrix(random);
416 SkRect rect = GrTest::TestRect(random);
417 SkRect devRect = GrTest::TestRect(random);
418 return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRect);
joshualitt9ff64252015-08-10 09:03:51 -0700419}
420
421#endif