blob: ffbab9654e52d61f127a0f8ffa0020fc2ba9ef58 [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
bsalomon08d14152016-06-30 12:45:18 -070010#include "GrBatchFlushState.h"
joshualitt37eb1842015-08-12 06:36:57 -070011#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"
bsalomon08d14152016-06-30 12:45:18 -070018#include "GrVertexBatch.h"
joshualitt9ff64252015-08-10 09:03:51 -070019
20GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
21
22static void set_inset_fan(SkPoint* pts, size_t stride,
23 const SkRect& r, SkScalar dx, SkScalar dy) {
24 pts->setRectFan(r.fLeft + dx, r.fTop + dy,
25 r.fRight - dx, r.fBottom - dy, stride);
26}
27
joshualitt27801bf2015-08-12 12:52:47 -070028static const int kNumAAFillRectsInIndexBuffer = 256;
29static const int kVertsPerAAFillRect = 8;
30static const int kIndicesPerAAFillRect = 30;
31
cdalton397536c2016-03-25 12:15:03 -070032const GrBuffer* get_index_buffer(GrResourceProvider* resourceProvider) {
joshualitt27801bf2015-08-12 12:52:47 -070033 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
34
35 static const uint16_t gFillAARectIdx[] = {
36 0, 1, 5, 5, 4, 0,
37 1, 2, 6, 6, 5, 1,
38 2, 3, 7, 7, 6, 2,
39 3, 0, 4, 4, 7, 3,
40 4, 5, 6, 6, 7, 4,
41 };
42 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect);
43 return resourceProvider->findOrCreateInstancedIndexBuffer(gFillAARectIdx,
44 kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect,
45 gAAFillRectIndexBufferKey);
46}
47
bungeman06ca8ec2016-06-09 08:01:03 -070048static sk_sp<GrGeometryProcessor> create_fill_rect_gp(
joshualittcd47b712015-08-18 07:25:38 -070049 const SkMatrix& viewMatrix,
ethannicholasff210322015-11-24 12:10:10 -080050 const GrXPOverridesForBatch& overrides,
joshualittcd47b712015-08-18 07:25:38 -070051 GrDefaultGeoProcFactory::LocalCoords::Type localCoordsType) {
52 using namespace GrDefaultGeoProcFactory;
53
54 Color color(Color::kAttribute_Type);
55 Coverage::Type coverageType;
56 // TODO remove coverage if coverage is ignored
57 /*if (coverageIgnored) {
58 coverageType = Coverage::kNone_Type;
ethannicholasff210322015-11-24 12:10:10 -080059 } else*/ if (overrides.canTweakAlphaForCoverage()) {
joshualittcd47b712015-08-18 07:25:38 -070060 coverageType = Coverage::kSolid_Type;
61 } else {
62 coverageType = Coverage::kAttribute_Type;
63 }
64 Coverage coverage(coverageType);
65
66 // We assume the caller has inverted the viewmatrix
67 if (LocalCoords::kHasExplicit_Type == localCoordsType) {
68 LocalCoords localCoords(localCoordsType);
bungeman06ca8ec2016-06-09 08:01:03 -070069 return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
joshualittcd47b712015-08-18 07:25:38 -070070 } else {
ethannicholasff210322015-11-24 12:10:10 -080071 LocalCoords localCoords(overrides.readsLocalCoords() ? localCoordsType :
72 LocalCoords::kUnused_Type);
bungeman06ca8ec2016-06-09 08:01:03 -070073 return MakeForDeviceSpace(color, coverage, localCoords, viewMatrix);
joshualittcd47b712015-08-18 07:25:38 -070074 }
75}
76
77static void generate_aa_fill_rect_geometry(intptr_t verts,
78 size_t vertexStride,
79 GrColor color,
80 const SkMatrix& viewMatrix,
81 const SkRect& rect,
82 const SkRect& devRect,
ethannicholasff210322015-11-24 12:10:10 -080083 const GrXPOverridesForBatch& overrides,
joshualittcd47b712015-08-18 07:25:38 -070084 const SkMatrix* localMatrix) {
85 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
86 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride);
87
robertphillips0851d2d2016-06-02 05:21:34 -070088 SkScalar inset;
joshualittcd47b712015-08-18 07:25:38 -070089
90 if (viewMatrix.rectStaysRect()) {
robertphillips0851d2d2016-06-02 05:21:34 -070091 inset = SkMinScalar(devRect.width(), SK_Scalar1);
92 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
93
joshualittcd47b712015-08-18 07:25:38 -070094 set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_ScalarHalf);
95 set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset);
96 } else {
97 // compute transformed (1, 0) and (0, 1) vectors
98 SkVector vec[2] = {
99 { viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY] },
100 { viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY] }
101 };
102
robertphillips0851d2d2016-06-02 05:21:34 -0700103 SkScalar len1 = SkPoint::Normalize(&vec[0]);
joshualittcd47b712015-08-18 07:25:38 -0700104 vec[0].scale(SK_ScalarHalf);
robertphillips0851d2d2016-06-02 05:21:34 -0700105 SkScalar len2 = SkPoint::Normalize(&vec[1]);
joshualittcd47b712015-08-18 07:25:38 -0700106 vec[1].scale(SK_ScalarHalf);
107
robertphillips0851d2d2016-06-02 05:21:34 -0700108 inset = SkMinScalar(len1 * rect.width(), SK_Scalar1);
109 inset = SK_ScalarHalf * SkMinScalar(inset, len2 * rect.height());
110
joshualittcd47b712015-08-18 07:25:38 -0700111 // create the rotated rect
112 fan0Pos->setRectFan(rect.fLeft, rect.fTop,
113 rect.fRight, rect.fBottom, vertexStride);
114 viewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4);
115
116 // Now create the inset points and then outset the original
117 // rotated points
118
119 // TL
120 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) =
121 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1];
122 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1];
123 // BL
124 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) =
125 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1];
126 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1];
127 // BR
128 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) =
129 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1];
130 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1];
131 // TR
132 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) =
133 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1];
134 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1];
135 }
136
137 if (localMatrix) {
138 SkMatrix invViewMatrix;
139 if (!viewMatrix.invert(&invViewMatrix)) {
140 SkASSERT(false);
141 invViewMatrix = SkMatrix::I();
142 }
143 SkMatrix localCoordMatrix;
144 localCoordMatrix.setConcat(*localMatrix, invViewMatrix);
145 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(verts + sizeof(SkPoint) + sizeof(GrColor));
146 localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8);
147 }
148
ethannicholasff210322015-11-24 12:10:10 -0800149 bool tweakAlphaForCoverage = overrides.canTweakAlphaForCoverage();
joshualittcd47b712015-08-18 07:25:38 -0700150
151 // Make verts point to vertex color and then set all the color and coverage vertex attrs
152 // values.
153 verts += sizeof(SkPoint);
154
155 // The coverage offset is always the last vertex attribute
156 intptr_t coverageOffset = vertexStride - sizeof(GrColor) - sizeof(SkPoint);
157 for (int i = 0; i < 4; ++i) {
158 if (tweakAlphaForCoverage) {
159 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
160 } else {
161 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
162 *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = 0;
163 }
164 }
165
166 int scale;
167 if (inset < SK_ScalarHalf) {
168 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
169 SkASSERT(scale >= 0 && scale <= 255);
170 } else {
171 scale = 0xff;
172 }
173
174 verts += 4 * vertexStride;
175
176 float innerCoverage = GrNormalizeByteToFloat(scale);
177 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
178
179 for (int i = 0; i < 4; ++i) {
180 if (tweakAlphaForCoverage) {
181 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
182 } else {
183 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
184 *reinterpret_cast<float*>(verts + i * vertexStride +
185 coverageOffset) = innerCoverage;
186 }
187 }
188}
189
bsalomon08d14152016-06-30 12:45:18 -0700190class AAFillRectNoLocalMatrixBatch : public GrVertexBatch {
joshualitt2ad37be2015-08-18 10:16:01 -0700191public:
bsalomon08d14152016-06-30 12:45:18 -0700192 DEFINE_BATCH_CLASS_ID
bsalomon0fdec8a2016-07-01 06:31:25 -0700193 AAFillRectNoLocalMatrixBatch(GrColor color,
194 const SkMatrix& viewMatrix,
195 const SkRect& rect,
196 const SkRect& devRect) : INHERITED(ClassID()) {
197 fRects.emplace_back(RectInfo{color, viewMatrix, rect, devRect});
198 fBounds = devRect;
199 }
bsalomon08d14152016-06-30 12:45:18 -0700200
bsalomonbc9b6a42016-07-01 05:35:51 -0700201 const char* name() const override { return "AAFillRectBatchNoLocalMatrix"; }
bsalomon08d14152016-06-30 12:45:18 -0700202
203 SkString dumpInfo() const override {
204 SkString str;
bsalomon0fdec8a2016-07-01 06:31:25 -0700205 str.appendf("# batched: %d\n", fRects.count());
206 for (int i = 0; i < fRects.count(); ++i) {
207 const RectInfo& info = fRects[i];
bsalomonbc9b6a42016-07-01 05:35:51 -0700208 str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
bsalomon0fdec8a2016-07-01 06:31:25 -0700209 i, info.fColor,
210 info.fRect.fLeft, info.fRect.fTop, info.fRect.fRight, info.fRect.fBottom);
bsalomon08d14152016-06-30 12:45:18 -0700211 }
212 str.append(INHERITED::dumpInfo());
213 return str;
214 }
215
216 void computePipelineOptimizations(GrInitInvariantOutput* color,
217 GrInitInvariantOutput* coverage,
218 GrBatchToXPOverrides* overrides) const override {
bsalomon0fdec8a2016-07-01 06:31:25 -0700219 // When this is called on a batch, there is only one rect
220 color->setKnownFourComponents(fRects[0].fColor);
bsalomonbc9b6a42016-07-01 05:35:51 -0700221 coverage->setUnknownSingleComponent();
bsalomon08d14152016-06-30 12:45:18 -0700222 }
223
224 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
bsalomon0fdec8a2016-07-01 06:31:25 -0700225 overrides.getOverrideColorIfSet(&fRects[0].fColor);
bsalomon08d14152016-06-30 12:45:18 -0700226 fOverrides = overrides;
227 }
228
bsalomon08d14152016-06-30 12:45:18 -0700229private:
bsalomon08d14152016-06-30 12:45:18 -0700230 AAFillRectNoLocalMatrixBatch() : INHERITED(ClassID()) {}
231
232 void onPrepareDraws(Target* target) const override {
bsalomonbc9b6a42016-07-01 05:35:51 -0700233 sk_sp<GrGeometryProcessor> gp =
bsalomon0fdec8a2016-07-01 06:31:25 -0700234 create_fill_rect_gp(fRects[0].fViewMatrix, fOverrides,
bsalomonbc9b6a42016-07-01 05:35:51 -0700235 GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type);
bsalomon08d14152016-06-30 12:45:18 -0700236 if (!gp) {
237 SkDebugf("Couldn't create GrGeometryProcessor\n");
238 return;
239 }
bsalomonbc9b6a42016-07-01 05:35:51 -0700240 SkASSERT(fOverrides.canTweakAlphaForCoverage() ?
241 gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
242 gp->getVertexStride() ==
243 sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
bsalomon08d14152016-06-30 12:45:18 -0700244
245 size_t vertexStride = gp->getVertexStride();
bsalomon08d14152016-06-30 12:45:18 -0700246
bsalomonbc9b6a42016-07-01 05:35:51 -0700247 SkAutoTUnref<const GrBuffer> indexBuffer(get_index_buffer(target->resourceProvider()));
bsalomon08d14152016-06-30 12:45:18 -0700248 InstancedHelper helper;
249 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
bsalomonbc9b6a42016-07-01 05:35:51 -0700250 indexBuffer, kVertsPerAAFillRect,
bsalomon0fdec8a2016-07-01 06:31:25 -0700251 kIndicesPerAAFillRect, fRects.count());
bsalomon08d14152016-06-30 12:45:18 -0700252 if (!vertices || !indexBuffer) {
253 SkDebugf("Could not allocate vertices\n");
254 return;
255 }
256
bsalomon0fdec8a2016-07-01 06:31:25 -0700257 for (int i = 0; i < fRects.count(); i++) {
bsalomon08d14152016-06-30 12:45:18 -0700258 intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
bsalomonbc9b6a42016-07-01 05:35:51 -0700259 i * kVertsPerAAFillRect * vertexStride;
260 generate_aa_fill_rect_geometry(verts, vertexStride,
bsalomon0fdec8a2016-07-01 06:31:25 -0700261 fRects[i].fColor, fRects[i].fViewMatrix,
262 fRects[i].fRect, fRects[i].fDevRect, fOverrides,
bsalomonbc9b6a42016-07-01 05:35:51 -0700263 nullptr);
bsalomon08d14152016-06-30 12:45:18 -0700264 }
265 helper.recordDraw(target, gp.get());
266 }
267
bsalomon08d14152016-06-30 12:45:18 -0700268 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
269 AAFillRectNoLocalMatrixBatch* that = t->cast<AAFillRectNoLocalMatrixBatch>();
270 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
271 that->bounds(), caps)) {
272 return false;
273 }
274
bsalomonbc9b6a42016-07-01 05:35:51 -0700275 // We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses
276 // local coords then we won't be able to batch. We could actually upload the viewmatrix
277 // using vertex attributes in these cases, but haven't investigated that
278 if (fOverrides.readsLocalCoords() &&
bsalomon0fdec8a2016-07-01 06:31:25 -0700279 !fRects[0].fViewMatrix.cheapEqualTo(that->fRects[0].fViewMatrix)) {
bsalomon08d14152016-06-30 12:45:18 -0700280 return false;
281 }
282
283 // In the event of two batches, one who can tweak, one who cannot, we just fall back to
284 // not tweaking
285 if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
286 fOverrides = that->fOverrides;
287 }
288
bsalomon0fdec8a2016-07-01 06:31:25 -0700289 fRects.push_back_n(that->fRects.count(), that->fRects.begin());
bsalomon08d14152016-06-30 12:45:18 -0700290 this->joinBounds(that->bounds());
291 return true;
292 }
293
bsalomon0fdec8a2016-07-01 06:31:25 -0700294 struct RectInfo {
295 GrColor fColor;
296 SkMatrix fViewMatrix;
297 SkRect fRect;
298 SkRect fDevRect;
299 };
300
bsalomon08d14152016-06-30 12:45:18 -0700301 GrXPOverridesForBatch fOverrides;
bsalomon0fdec8a2016-07-01 06:31:25 -0700302 SkSTArray<1, RectInfo, true> fRects;
bsalomon08d14152016-06-30 12:45:18 -0700303
304 typedef GrVertexBatch INHERITED;
joshualitt147dc062015-08-12 11:51:46 -0700305};
306
bsalomon08d14152016-06-30 12:45:18 -0700307class AAFillRectLocalMatrixBatch : public GrVertexBatch {
joshualitt147dc062015-08-12 11:51:46 -0700308public:
bsalomon08d14152016-06-30 12:45:18 -0700309 DEFINE_BATCH_CLASS_ID
310
bsalomon0fdec8a2016-07-01 06:31:25 -0700311 AAFillRectLocalMatrixBatch(GrColor color,
312 const SkMatrix& viewMatrix,
313 const SkMatrix& localMatrix,
314 const SkRect& rect,
315 const SkRect& devRect) : INHERITED(ClassID()) {
316 fRects.emplace_back(RectInfo{color, viewMatrix, localMatrix, rect, devRect});
317 fBounds = devRect;
318 }
bsalomon08d14152016-06-30 12:45:18 -0700319
bsalomonbc9b6a42016-07-01 05:35:51 -0700320 const char* name() const override { return "AAFillRectBatchLocalMatrix"; }
bsalomon08d14152016-06-30 12:45:18 -0700321
322 SkString dumpInfo() const override {
323 SkString str;
bsalomon0fdec8a2016-07-01 06:31:25 -0700324 str.appendf("# batched: %d\n", fRects.count());
325 for (int i = 0; i < fRects.count(); ++i) {
326 const RectInfo& info = fRects[i];
bsalomonbc9b6a42016-07-01 05:35:51 -0700327 str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
bsalomon0fdec8a2016-07-01 06:31:25 -0700328 i, info.fColor,
329 info.fRect.fLeft, info.fRect.fTop, info.fRect.fRight, info.fRect.fBottom);
bsalomon08d14152016-06-30 12:45:18 -0700330 }
331 str.append(INHERITED::dumpInfo());
332 return str;
333 }
334
335 void computePipelineOptimizations(GrInitInvariantOutput* color,
336 GrInitInvariantOutput* coverage,
337 GrBatchToXPOverrides* overrides) const override {
bsalomon0fdec8a2016-07-01 06:31:25 -0700338 // When this is called on a batch, there is only one rect
339 color->setKnownFourComponents(fRects[0].fColor);
bsalomonbc9b6a42016-07-01 05:35:51 -0700340 coverage->setUnknownSingleComponent();
bsalomon08d14152016-06-30 12:45:18 -0700341 }
342
343 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
bsalomon0fdec8a2016-07-01 06:31:25 -0700344 overrides.getOverrideColorIfSet(&fRects[0].fColor);
bsalomon08d14152016-06-30 12:45:18 -0700345 fOverrides = overrides;
346 }
347
bsalomon08d14152016-06-30 12:45:18 -0700348private:
bsalomon08d14152016-06-30 12:45:18 -0700349 AAFillRectLocalMatrixBatch() : INHERITED(ClassID()) {}
350
351 void onPrepareDraws(Target* target) const override {
bsalomonbc9b6a42016-07-01 05:35:51 -0700352 sk_sp<GrGeometryProcessor> gp =
bsalomon0fdec8a2016-07-01 06:31:25 -0700353 create_fill_rect_gp(fRects[0].fViewMatrix, fOverrides,
bsalomonbc9b6a42016-07-01 05:35:51 -0700354 GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type);
bsalomon08d14152016-06-30 12:45:18 -0700355 if (!gp) {
356 SkDebugf("Couldn't create GrGeometryProcessor\n");
357 return;
358 }
bsalomonbc9b6a42016-07-01 05:35:51 -0700359 SkASSERT(fOverrides.canTweakAlphaForCoverage() ?
360 gp->getVertexStride() ==
361 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
362 gp->getVertexStride() ==
363 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordCoverage));
bsalomon08d14152016-06-30 12:45:18 -0700364
365 size_t vertexStride = gp->getVertexStride();
bsalomon08d14152016-06-30 12:45:18 -0700366
bsalomonbc9b6a42016-07-01 05:35:51 -0700367 SkAutoTUnref<const GrBuffer> indexBuffer(get_index_buffer(target->resourceProvider()));
bsalomon08d14152016-06-30 12:45:18 -0700368 InstancedHelper helper;
369 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
bsalomonbc9b6a42016-07-01 05:35:51 -0700370 indexBuffer, kVertsPerAAFillRect,
bsalomon0fdec8a2016-07-01 06:31:25 -0700371 kIndicesPerAAFillRect, fRects.count());
bsalomon08d14152016-06-30 12:45:18 -0700372 if (!vertices || !indexBuffer) {
373 SkDebugf("Could not allocate vertices\n");
374 return;
375 }
376
bsalomon0fdec8a2016-07-01 06:31:25 -0700377 for (int i = 0; i < fRects.count(); i++) {
bsalomon08d14152016-06-30 12:45:18 -0700378 intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
bsalomonbc9b6a42016-07-01 05:35:51 -0700379 i * kVertsPerAAFillRect * vertexStride;
bsalomon0fdec8a2016-07-01 06:31:25 -0700380 generate_aa_fill_rect_geometry(verts, vertexStride, fRects[i].fColor,
381 fRects[i].fViewMatrix, fRects[i].fRect,
382 fRects[i].fDevRect, fOverrides,
383 &fRects[i].fLocalMatrix);
bsalomon08d14152016-06-30 12:45:18 -0700384 }
385 helper.recordDraw(target, gp.get());
386 }
387
bsalomon08d14152016-06-30 12:45:18 -0700388 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
389 AAFillRectLocalMatrixBatch* that = t->cast<AAFillRectLocalMatrixBatch>();
390 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
391 that->bounds(), caps)) {
392 return false;
393 }
394
bsalomon08d14152016-06-30 12:45:18 -0700395 // In the event of two batches, one who can tweak, one who cannot, we just fall back to
396 // not tweaking
397 if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
398 fOverrides = that->fOverrides;
399 }
400
bsalomon0fdec8a2016-07-01 06:31:25 -0700401 fRects.push_back_n(that->fRects.count(), that->fRects.begin());
bsalomon08d14152016-06-30 12:45:18 -0700402 this->joinBounds(that->bounds());
403 return true;
404 }
405
bsalomon0fdec8a2016-07-01 06:31:25 -0700406 struct RectInfo {
407 GrColor fColor;
408 SkMatrix fViewMatrix;
409 SkMatrix fLocalMatrix;
410 SkRect fRect;
411 SkRect fDevRect;
412 };
413
bsalomon08d14152016-06-30 12:45:18 -0700414 GrXPOverridesForBatch fOverrides;
bsalomon0fdec8a2016-07-01 06:31:25 -0700415 SkSTArray<1, RectInfo, true> fRects;
bsalomon08d14152016-06-30 12:45:18 -0700416
417 typedef GrVertexBatch INHERITED;
joshualitt147dc062015-08-12 11:51:46 -0700418};
419
joshualitt37eb1842015-08-12 06:36:57 -0700420namespace GrAAFillRectBatch {
joshualitt9ff64252015-08-10 09:03:51 -0700421
bsalomonabd30f52015-08-13 13:34:48 -0700422GrDrawBatch* Create(GrColor color,
423 const SkMatrix& viewMatrix,
424 const SkRect& rect,
425 const SkRect& devRect) {
bsalomon0fdec8a2016-07-01 06:31:25 -0700426 return new AAFillRectNoLocalMatrixBatch(color, viewMatrix, rect, devRect);
joshualitt147dc062015-08-12 11:51:46 -0700427}
428
bsalomonabd30f52015-08-13 13:34:48 -0700429GrDrawBatch* Create(GrColor color,
430 const SkMatrix& viewMatrix,
431 const SkMatrix& localMatrix,
432 const SkRect& rect,
433 const SkRect& devRect) {
bsalomon0fdec8a2016-07-01 06:31:25 -0700434 return new AAFillRectLocalMatrixBatch(color, viewMatrix, localMatrix, rect, devRect);
joshualitt9ff64252015-08-10 09:03:51 -0700435}
436
bsalomonc55271f2015-11-09 11:55:57 -0800437GrDrawBatch* Create(GrColor color,
438 const SkMatrix& viewMatrix,
439 const SkMatrix& localMatrix,
440 const SkRect& rect) {
441 SkRect devRect;
442 viewMatrix.mapRect(&devRect, rect);
443 return Create(color, viewMatrix, localMatrix, rect, devRect);
444}
445
446GrDrawBatch* CreateWithLocalRect(GrColor color,
447 const SkMatrix& viewMatrix,
448 const SkRect& rect,
449 const SkRect& localRect) {
450 SkRect devRect;
451 viewMatrix.mapRect(&devRect, rect);
452 SkMatrix localMatrix;
453 if (!localMatrix.setRectToRect(rect, localRect, SkMatrix::kFill_ScaleToFit)) {
454 return nullptr;
455 }
456 return Create(color, viewMatrix, localMatrix, rect, devRect);
457}
458
joshualitt37eb1842015-08-12 06:36:57 -0700459};
460
joshualitt9ff64252015-08-10 09:03:51 -0700461///////////////////////////////////////////////////////////////////////////////////////////////////
462
463#ifdef GR_TEST_UTILS
464
465#include "GrBatchTest.h"
466
bsalomonabd30f52015-08-13 13:34:48 -0700467DRAW_BATCH_TEST_DEFINE(AAFillRectBatch) {
joshualitt090ae8e2015-08-14 09:01:21 -0700468 GrColor color = GrRandomColor(random);
469 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
470 SkRect rect = GrTest::TestRect(random);
471 SkRect devRect = GrTest::TestRect(random);
472 return GrAAFillRectBatch::Create(color, viewMatrix, rect, devRect);
joshualitt147dc062015-08-12 11:51:46 -0700473}
474
bsalomonabd30f52015-08-13 13:34:48 -0700475DRAW_BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) {
joshualitt090ae8e2015-08-14 09:01:21 -0700476 GrColor color = GrRandomColor(random);
477 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
478 SkMatrix localMatrix = GrTest::TestMatrix(random);
479 SkRect rect = GrTest::TestRect(random);
480 SkRect devRect = GrTest::TestRect(random);
481 return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRect);
joshualitt9ff64252015-08-10 09:03:51 -0700482}
483
484#endif