blob: b2a3de9ee8da06b84d43c6e2c830d73dc63130ff [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
193
194 struct Geometry {
195 SkMatrix fViewMatrix;
196 SkRect fRect;
197 SkRect fDevRect;
198 GrColor fColor;
199 };
200
201 static AAFillRectNoLocalMatrixBatch* Create() { return new AAFillRectNoLocalMatrixBatch; }
202
203 const char* name() const override { return Name(); }
204
205 SkString dumpInfo() const override {
206 SkString str;
207 str.appendf("# batched: %d\n", fGeoData.count());
208 for (int i = 0; i < fGeoData.count(); ++i) {
209 str.append(DumpInfo(fGeoData[i], i));
210 }
211 str.append(INHERITED::dumpInfo());
212 return str;
213 }
214
215 void computePipelineOptimizations(GrInitInvariantOutput* color,
216 GrInitInvariantOutput* coverage,
217 GrBatchToXPOverrides* overrides) const override {
218 // When this is called on a batch, there is only one geometry bundle
219 color->setKnownFourComponents(fGeoData[0].fColor);
220 InitInvariantOutputCoverage(coverage);
221 }
222
223 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
224 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
225 fOverrides = overrides;
226 }
227
228 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
229
230 // After seeding, the client should call init() so the Batch can initialize itself
231 void init() {
232 const Geometry& geo = fGeoData[0];
233 SetBounds(geo, &fBounds);
234 }
235
236 void updateBoundsAfterAppend() {
237 const Geometry& geo = fGeoData.back();
238 UpdateBoundsAfterAppend(geo, &fBounds);
239 }
240
241private:
joshualitt2ad37be2015-08-18 10:16:01 -0700242 static const int kVertsPerInstance = kVertsPerAAFillRect;
243 static const int kIndicesPerInstance = kIndicesPerAAFillRect;
244
joshualitt2244c272015-08-21 10:33:15 -0700245 static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
246 out->setUnknownSingleComponent();
247 }
248
cdalton397536c2016-03-25 12:15:03 -0700249 static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
joshualitt2ad37be2015-08-18 10:16:01 -0700250 return get_index_buffer(rp);
251 }
joshualitt2244c272015-08-21 10:33:15 -0700252
joshualitt2244c272015-08-21 10:33:15 -0700253 static void SetBounds(const Geometry& geo, SkRect* outBounds) {
254 *outBounds = geo.fDevRect;
255 }
joshualittaa37a962015-09-18 13:03:25 -0700256
joshualittaa37a962015-09-18 13:03:25 -0700257 static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
258 outBounds->join(geo.fDevRect);
259 }
joshualitt147dc062015-08-12 11:51:46 -0700260
joshualitt2244c272015-08-21 10:33:15 -0700261 static const char* Name() { return "AAFillRectBatchNoLocalMatrix"; }
joshualitt2ad37be2015-08-18 10:16:01 -0700262
robertphillips783a4da2015-11-19 14:00:02 -0800263 static SkString DumpInfo(const Geometry& geo, int index) {
robertphillipse004bfc2015-11-16 09:06:59 -0800264 SkString str;
robertphillips783a4da2015-11-19 14:00:02 -0800265 str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
266 index,
robertphillipse004bfc2015-11-16 09:06:59 -0800267 geo.fColor,
268 geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
269 return str;
270 }
271
joshualitt2244c272015-08-21 10:33:15 -0700272 static bool CanCombine(const Geometry& mine, const Geometry& theirs,
ethannicholasff210322015-11-24 12:10:10 -0800273 const GrXPOverridesForBatch& overrides) {
joshualitt147dc062015-08-12 11:51:46 -0700274 // We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses
275 // local coords then we won't be able to batch. We could actually upload the viewmatrix
276 // using vertex attributes in these cases, but haven't investigated that
ethannicholasff210322015-11-24 12:10:10 -0800277 return !overrides.readsLocalCoords() || mine.fViewMatrix.cheapEqualTo(theirs.fViewMatrix);
joshualitt147dc062015-08-12 11:51:46 -0700278 }
279
bungeman06ca8ec2016-06-09 08:01:03 -0700280 static sk_sp<GrGeometryProcessor> MakeGP(const Geometry& geo,
bsalomon08d14152016-06-30 12:45:18 -0700281 const GrXPOverridesForBatch& overrides) {
bungeman06ca8ec2016-06-09 08:01:03 -0700282 sk_sp<GrGeometryProcessor> gp =
ethannicholasff210322015-11-24 12:10:10 -0800283 create_fill_rect_gp(geo.fViewMatrix, overrides,
joshualittcd47b712015-08-18 07:25:38 -0700284 GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type);
285
ethannicholasff210322015-11-24 12:10:10 -0800286 SkASSERT(overrides.canTweakAlphaForCoverage() ?
joshualittcd47b712015-08-18 07:25:38 -0700287 gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
288 gp->getVertexStride() ==
289 sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
290 return gp;
joshualitt147dc062015-08-12 11:51:46 -0700291 }
292
joshualitt2244c272015-08-21 10:33:15 -0700293 static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
ethannicholasff210322015-11-24 12:10:10 -0800294 const GrXPOverridesForBatch& overrides) {
joshualittcd47b712015-08-18 07:25:38 -0700295 generate_aa_fill_rect_geometry(vertices, vertexStride,
halcanary9d524f22016-03-29 09:03:52 -0700296 geo.fColor, geo.fViewMatrix, geo.fRect, geo.fDevRect,
ethannicholasff210322015-11-24 12:10:10 -0800297 overrides, nullptr);
joshualitt147dc062015-08-12 11:51:46 -0700298 }
bsalomon08d14152016-06-30 12:45:18 -0700299
300 AAFillRectNoLocalMatrixBatch() : INHERITED(ClassID()) {}
301
302 void onPrepareDraws(Target* target) const override {
303 sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides));
304 if (!gp) {
305 SkDebugf("Couldn't create GrGeometryProcessor\n");
306 return;
307 }
308
309 size_t vertexStride = gp->getVertexStride();
310 int instanceCount = fGeoData.count();
311
312 SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider()));
313 InstancedHelper helper;
314 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
315 indexBuffer, kVertsPerInstance,
316 kIndicesPerInstance, instanceCount);
317 if (!vertices || !indexBuffer) {
318 SkDebugf("Could not allocate vertices\n");
319 return;
320 }
321
322 for (int i = 0; i < instanceCount; i++) {
323 intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
324 i * kVertsPerInstance * vertexStride;
325 Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
326 }
327 helper.recordDraw(target, gp.get());
328 }
329
330 const Geometry& seedGeometry() const { return fGeoData[0]; }
331
332 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
333 AAFillRectNoLocalMatrixBatch* that = t->cast<AAFillRectNoLocalMatrixBatch>();
334 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
335 that->bounds(), caps)) {
336 return false;
337 }
338
339 if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
340 return false;
341 }
342
343 // In the event of two batches, one who can tweak, one who cannot, we just fall back to
344 // not tweaking
345 if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
346 fOverrides = that->fOverrides;
347 }
348
349 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
350 this->joinBounds(that->bounds());
351 return true;
352 }
353
354 GrXPOverridesForBatch fOverrides;
355 SkSTArray<1, Geometry, true> fGeoData;
356
357 typedef GrVertexBatch INHERITED;
joshualitt147dc062015-08-12 11:51:46 -0700358};
359
bsalomon08d14152016-06-30 12:45:18 -0700360class AAFillRectLocalMatrixBatch : public GrVertexBatch {
joshualitt147dc062015-08-12 11:51:46 -0700361public:
bsalomon08d14152016-06-30 12:45:18 -0700362 DEFINE_BATCH_CLASS_ID
363
joshualitt147dc062015-08-12 11:51:46 -0700364 struct Geometry {
365 SkMatrix fViewMatrix;
366 SkMatrix fLocalMatrix;
joshualitt40ac15a2015-08-14 08:45:39 -0700367 SkRect fRect;
joshualitt147dc062015-08-12 11:51:46 -0700368 SkRect fDevRect;
369 GrColor fColor;
370 };
371
bsalomon08d14152016-06-30 12:45:18 -0700372 static AAFillRectLocalMatrixBatch* Create() { return new AAFillRectLocalMatrixBatch; }
373
374 const char* name() const override { return Name(); }
375
376 SkString dumpInfo() const override {
377 SkString str;
378 str.appendf("# batched: %d\n", fGeoData.count());
379 for (int i = 0; i < fGeoData.count(); ++i) {
380 str.append(DumpInfo(fGeoData[i], i));
381 }
382 str.append(INHERITED::dumpInfo());
383 return str;
384 }
385
386 void computePipelineOptimizations(GrInitInvariantOutput* color,
387 GrInitInvariantOutput* coverage,
388 GrBatchToXPOverrides* overrides) const override {
389 // When this is called on a batch, there is only one geometry bundle
390 color->setKnownFourComponents(fGeoData[0].fColor);
391 InitInvariantOutputCoverage(coverage);
392 }
393
394 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
395 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
396 fOverrides = overrides;
397 }
398
399 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
400
401 // After seeding, the client should call init() so the Batch can initialize itself
402 void init() {
403 const Geometry& geo = fGeoData[0];
404 SetBounds(geo, &fBounds);
405 }
406
407 void updateBoundsAfterAppend() {
408 const Geometry& geo = fGeoData.back();
409 UpdateBoundsAfterAppend(geo, &fBounds);
410 }
411
412private:
413 static const int kVertsPerInstance = kVertsPerAAFillRect;
414 static const int kIndicesPerInstance = kIndicesPerAAFillRect;
415
416 static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
417 out->setUnknownSingleComponent();
418 }
419
420 static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
421 return get_index_buffer(rp);
422 }
423
424 static void SetBounds(const Geometry& geo, SkRect* outBounds) {
425 *outBounds = geo.fDevRect;
426 }
427
428 static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
429 outBounds->join(geo.fDevRect);
430 }
431
joshualitt2244c272015-08-21 10:33:15 -0700432 static const char* Name() { return "AAFillRectBatchLocalMatrix"; }
joshualitt2ad37be2015-08-18 10:16:01 -0700433
robertphillips783a4da2015-11-19 14:00:02 -0800434 static SkString DumpInfo(const Geometry& geo, int index) {
robertphillipse004bfc2015-11-16 09:06:59 -0800435 SkString str;
robertphillips783a4da2015-11-19 14:00:02 -0800436 str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
437 index,
robertphillipse004bfc2015-11-16 09:06:59 -0800438 geo.fColor,
439 geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
440 return str;
441 }
442
joshualitt2244c272015-08-21 10:33:15 -0700443 static bool CanCombine(const Geometry& mine, const Geometry& theirs,
ethannicholasff210322015-11-24 12:10:10 -0800444 const GrXPOverridesForBatch& overrides) {
joshualitt147dc062015-08-12 11:51:46 -0700445 return true;
446 }
447
bungeman06ca8ec2016-06-09 08:01:03 -0700448 static sk_sp<GrGeometryProcessor> MakeGP(const Geometry& geo,
ethannicholasff210322015-11-24 12:10:10 -0800449 const GrXPOverridesForBatch& overrides) {
bungeman06ca8ec2016-06-09 08:01:03 -0700450 sk_sp<GrGeometryProcessor> gp =
ethannicholasff210322015-11-24 12:10:10 -0800451 create_fill_rect_gp(geo.fViewMatrix, overrides,
joshualittcd47b712015-08-18 07:25:38 -0700452 GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type);
453
ethannicholasff210322015-11-24 12:10:10 -0800454 SkASSERT(overrides.canTweakAlphaForCoverage() ?
joshualittcd47b712015-08-18 07:25:38 -0700455 gp->getVertexStride() ==
456 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
457 gp->getVertexStride() ==
458 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordCoverage));
459 return gp;
joshualitt147dc062015-08-12 11:51:46 -0700460 }
461
joshualitt2244c272015-08-21 10:33:15 -0700462 static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
ethannicholasff210322015-11-24 12:10:10 -0800463 const GrXPOverridesForBatch& overrides) {
joshualittcd47b712015-08-18 07:25:38 -0700464 generate_aa_fill_rect_geometry(vertices, vertexStride,
halcanary9d524f22016-03-29 09:03:52 -0700465 geo.fColor, geo.fViewMatrix, geo.fRect, geo.fDevRect,
ethannicholasff210322015-11-24 12:10:10 -0800466 overrides, &geo.fLocalMatrix);
joshualitt147dc062015-08-12 11:51:46 -0700467 }
bsalomon08d14152016-06-30 12:45:18 -0700468
469 AAFillRectLocalMatrixBatch() : INHERITED(ClassID()) {}
470
471 void onPrepareDraws(Target* target) const override {
472 sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides));
473 if (!gp) {
474 SkDebugf("Couldn't create GrGeometryProcessor\n");
475 return;
476 }
477
478 size_t vertexStride = gp->getVertexStride();
479 int instanceCount = fGeoData.count();
480
481 SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider()));
482 InstancedHelper helper;
483 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
484 indexBuffer, kVertsPerInstance,
485 kIndicesPerInstance, instanceCount);
486 if (!vertices || !indexBuffer) {
487 SkDebugf("Could not allocate vertices\n");
488 return;
489 }
490
491 for (int i = 0; i < instanceCount; i++) {
492 intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
493 i * kVertsPerInstance * vertexStride;
494 Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
495 }
496 helper.recordDraw(target, gp.get());
497 }
498
499 const Geometry& seedGeometry() const { return fGeoData[0]; }
500
501 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
502 AAFillRectLocalMatrixBatch* that = t->cast<AAFillRectLocalMatrixBatch>();
503 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
504 that->bounds(), caps)) {
505 return false;
506 }
507
508 if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
509 return false;
510 }
511
512 // In the event of two batches, one who can tweak, one who cannot, we just fall back to
513 // not tweaking
514 if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
515 fOverrides = that->fOverrides;
516 }
517
518 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
519 this->joinBounds(that->bounds());
520 return true;
521 }
522
523 GrXPOverridesForBatch fOverrides;
524 SkSTArray<1, Geometry, true> fGeoData;
525
526 typedef GrVertexBatch INHERITED;
joshualitt147dc062015-08-12 11:51:46 -0700527};
528
bsalomon08d14152016-06-30 12:45:18 -0700529inline static void append_to_batch(AAFillRectNoLocalMatrixBatch* batch, GrColor color,
joshualittaa37a962015-09-18 13:03:25 -0700530 const SkMatrix& viewMatrix, const SkRect& rect,
531 const SkRect& devRect) {
bsalomon08d14152016-06-30 12:45:18 -0700532 AAFillRectNoLocalMatrixBatch::Geometry& geo = batch->geoData()->push_back();
joshualittaa37a962015-09-18 13:03:25 -0700533 geo.fColor = color;
534 geo.fViewMatrix = viewMatrix;
535 geo.fRect = rect;
536 geo.fDevRect = devRect;
537}
538
bsalomon08d14152016-06-30 12:45:18 -0700539inline static void append_to_batch(AAFillRectLocalMatrixBatch* batch, GrColor color,
joshualittaa37a962015-09-18 13:03:25 -0700540 const SkMatrix& viewMatrix, const SkMatrix& localMatrix,
541 const SkRect& rect, const SkRect& devRect) {
bsalomon08d14152016-06-30 12:45:18 -0700542 AAFillRectLocalMatrixBatch::Geometry& geo = batch->geoData()->push_back();
joshualittaa37a962015-09-18 13:03:25 -0700543 geo.fColor = color;
544 geo.fViewMatrix = viewMatrix;
545 geo.fLocalMatrix = localMatrix;
546 geo.fRect = rect;
547 geo.fDevRect = devRect;
548}
549
joshualitt37eb1842015-08-12 06:36:57 -0700550namespace GrAAFillRectBatch {
joshualitt9ff64252015-08-10 09:03:51 -0700551
bsalomonabd30f52015-08-13 13:34:48 -0700552GrDrawBatch* Create(GrColor color,
553 const SkMatrix& viewMatrix,
554 const SkRect& rect,
555 const SkRect& devRect) {
bsalomon08d14152016-06-30 12:45:18 -0700556 AAFillRectNoLocalMatrixBatch* batch = AAFillRectNoLocalMatrixBatch::Create();
joshualittaa37a962015-09-18 13:03:25 -0700557 append_to_batch(batch, color, viewMatrix, rect, devRect);
joshualitt147dc062015-08-12 11:51:46 -0700558 batch->init();
559 return batch;
560}
561
bsalomonabd30f52015-08-13 13:34:48 -0700562GrDrawBatch* Create(GrColor color,
563 const SkMatrix& viewMatrix,
564 const SkMatrix& localMatrix,
565 const SkRect& rect,
566 const SkRect& devRect) {
bsalomon08d14152016-06-30 12:45:18 -0700567 AAFillRectLocalMatrixBatch* batch = AAFillRectLocalMatrixBatch::Create();
joshualittaa37a962015-09-18 13:03:25 -0700568 append_to_batch(batch, color, viewMatrix, localMatrix, rect, devRect);
joshualitt147dc062015-08-12 11:51:46 -0700569 batch->init();
570 return batch;
joshualitt9ff64252015-08-10 09:03:51 -0700571}
572
bsalomonc55271f2015-11-09 11:55:57 -0800573GrDrawBatch* Create(GrColor color,
574 const SkMatrix& viewMatrix,
575 const SkMatrix& localMatrix,
576 const SkRect& rect) {
577 SkRect devRect;
578 viewMatrix.mapRect(&devRect, rect);
579 return Create(color, viewMatrix, localMatrix, rect, devRect);
580}
581
582GrDrawBatch* CreateWithLocalRect(GrColor color,
583 const SkMatrix& viewMatrix,
584 const SkRect& rect,
585 const SkRect& localRect) {
586 SkRect devRect;
587 viewMatrix.mapRect(&devRect, rect);
588 SkMatrix localMatrix;
589 if (!localMatrix.setRectToRect(rect, localRect, SkMatrix::kFill_ScaleToFit)) {
590 return nullptr;
591 }
592 return Create(color, viewMatrix, localMatrix, rect, devRect);
593}
594
joshualittaa37a962015-09-18 13:03:25 -0700595void Append(GrBatch* origBatch,
596 GrColor color,
597 const SkMatrix& viewMatrix,
598 const SkRect& rect,
599 const SkRect& devRect) {
bsalomon08d14152016-06-30 12:45:18 -0700600 AAFillRectNoLocalMatrixBatch* batch = origBatch->cast<AAFillRectNoLocalMatrixBatch>();
joshualittaa37a962015-09-18 13:03:25 -0700601 append_to_batch(batch, color, viewMatrix, rect, devRect);
602 batch->updateBoundsAfterAppend();
603}
604
605void Append(GrBatch* origBatch,
606 GrColor color,
607 const SkMatrix& viewMatrix,
608 const SkMatrix& localMatrix,
609 const SkRect& rect,
610 const SkRect& devRect) {
bsalomon08d14152016-06-30 12:45:18 -0700611 AAFillRectLocalMatrixBatch* batch = origBatch->cast<AAFillRectLocalMatrixBatch>();
joshualittaa37a962015-09-18 13:03:25 -0700612 append_to_batch(batch, color, viewMatrix, localMatrix, rect, devRect);
613 batch->updateBoundsAfterAppend();
614}
615
joshualitt37eb1842015-08-12 06:36:57 -0700616};
617
joshualitt9ff64252015-08-10 09:03:51 -0700618///////////////////////////////////////////////////////////////////////////////////////////////////
619
620#ifdef GR_TEST_UTILS
621
622#include "GrBatchTest.h"
623
bsalomonabd30f52015-08-13 13:34:48 -0700624DRAW_BATCH_TEST_DEFINE(AAFillRectBatch) {
joshualitt090ae8e2015-08-14 09:01:21 -0700625 GrColor color = GrRandomColor(random);
626 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
627 SkRect rect = GrTest::TestRect(random);
628 SkRect devRect = GrTest::TestRect(random);
629 return GrAAFillRectBatch::Create(color, viewMatrix, rect, devRect);
joshualitt147dc062015-08-12 11:51:46 -0700630}
631
bsalomonabd30f52015-08-13 13:34:48 -0700632DRAW_BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) {
joshualitt090ae8e2015-08-14 09:01:21 -0700633 GrColor color = GrRandomColor(random);
634 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
635 SkMatrix localMatrix = GrTest::TestMatrix(random);
636 SkRect rect = GrTest::TestRect(random);
637 SkRect devRect = GrTest::TestRect(random);
638 return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRect);
joshualitt9ff64252015-08-10 09:03:51 -0700639}
640
641#endif