blob: ccd55c11ab6ddf4e2528b95ae1784e2b72f5e70c [file] [log] [blame]
Michael Ludwig69858532018-11-28 15:34:34 -05001/*
2 * Copyright 2018 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 "GrFillRectOp.h"
9
10#include "GrGeometryProcessor.h"
11#include "GrMeshDrawOp.h"
12#include "GrPaint.h"
13#include "GrQuad.h"
14#include "GrQuadPerEdgeAA.h"
15#include "GrSimpleMeshDrawOpHelper.h"
16#include "SkMatrix.h"
17#include "SkRect.h"
18#include "glsl/GrGLSLColorSpaceXformHelper.h"
19#include "glsl/GrGLSLGeometryProcessor.h"
20#include "glsl/GrGLSLVarying.h"
21
22namespace {
23
24using VertexSpec = GrQuadPerEdgeAA::VertexSpec;
25using ColorType = GrQuadPerEdgeAA::ColorType;
26
Michael Ludwigc96fc372019-01-08 15:46:15 -050027#ifdef SK_DEBUG
28static SkString dump_quad_info(int index, const GrPerspQuad& deviceQuad,
29 const GrPerspQuad& localQuad, const SkPMColor4f& color,
30 GrQuadAAFlags aaFlags) {
31 SkString str;
32 str.appendf("%d: Color: [%.2f, %.2f, %.2f, %.2f], Edge AA: l%u_t%u_r%u_b%u, \n"
33 " device quad: [(%.2f, %2.f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), "
34 "(%.2f, %.2f, %.2f)],\n"
35 " local quad: [(%.2f, %2.f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), "
36 "(%.2f, %.2f, %.2f)]\n",
37 index, color.fR, color.fG, color.fB, color.fA,
38 (uint32_t) (aaFlags & GrQuadAAFlags::kLeft),
39 (uint32_t) (aaFlags & GrQuadAAFlags::kTop),
40 (uint32_t) (aaFlags & GrQuadAAFlags::kRight),
41 (uint32_t) (aaFlags & GrQuadAAFlags::kBottom),
42 deviceQuad.x(0), deviceQuad.y(0), deviceQuad.w(0),
43 deviceQuad.x(1), deviceQuad.y(1), deviceQuad.w(1),
44 deviceQuad.x(2), deviceQuad.y(2), deviceQuad.w(2),
45 deviceQuad.x(3), deviceQuad.y(3), deviceQuad.w(3),
46 localQuad.x(0), localQuad.y(0), localQuad.w(0),
47 localQuad.x(1), localQuad.y(1), localQuad.w(1),
48 localQuad.x(2), localQuad.y(2), localQuad.w(2),
49 localQuad.x(3), localQuad.y(3), localQuad.w(3));
50 return str;
51}
52#endif
Michael Ludwig69858532018-11-28 15:34:34 -050053
Michael Ludwig69858532018-11-28 15:34:34 -050054class FillRectOp final : public GrMeshDrawOp {
55private:
56 using Helper = GrSimpleMeshDrawOpHelperWithStencil;
57
58public:
59 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
60 GrPaint&& paint,
61 GrAAType aaType,
62 GrQuadAAFlags edgeAA,
63 const GrUserStencilSettings* stencilSettings,
64 const GrPerspQuad& deviceQuad,
65 GrQuadType deviceQuadType,
66 const GrPerspQuad& localQuad,
67 GrQuadType localQuadType) {
68 // Clean up deviations between aaType and edgeAA
69 GrResolveAATypeForQuad(aaType, edgeAA, deviceQuad, deviceQuadType, &aaType, &edgeAA);
70
71 // Analyze the paint to see if it is compatible with scissor-clearing
72 SkPMColor4f color = paint.getColor4f();
73 // Only non-null if the paint can be turned into a clear, it can be a local pointer since
74 // the op ctor consumes the value right away if it's provided
75 SkPMColor4f* clearColor = nullptr;
76 if (paint.isTrivial() || paint.isConstantBlendedColor(&color)) {
77 clearColor = &color;
78 }
79
80 return Helper::FactoryHelper<FillRectOp>(context, std::move(paint), clearColor, aaType,
81 edgeAA, stencilSettings, deviceQuad, deviceQuadType, localQuad, localQuadType);
82 }
83
84 // Analysis of the GrPaint to determine the const blend color must be done before, passing
85 // nullptr for constBlendColor disables all scissor-clear optimizations (must keep the
86 // paintColor argument because it is assumed by the GrSimpleMeshDrawOpHelper). Similarly, aaType
87 // is passed to Helper in the initializer list, so incongruities between aaType and edgeFlags
88 // must be resolved prior to calling this constructor.
89 FillRectOp(Helper::MakeArgs args, SkPMColor4f paintColor, const SkPMColor4f* constBlendColor,
90 GrAAType aaType, GrQuadAAFlags edgeFlags, const GrUserStencilSettings* stencil,
91 const GrPerspQuad& deviceQuad, GrQuadType deviceQuadType,
92 const GrPerspQuad& localQuad, GrQuadType localQuadType)
93 : INHERITED(ClassID())
Michael Ludwigc96fc372019-01-08 15:46:15 -050094 , fHelper(args, aaType, stencil) {
Michael Ludwig69858532018-11-28 15:34:34 -050095 if (constBlendColor) {
96 // The GrPaint is compatible with clearing, and the constant blend color overrides the
97 // paint color (although in most cases they are probably the same)
98 paintColor = *constBlendColor;
99 // However, just because the paint is compatible, the device quad must also be a rect
100 // that is non-AA (AA aligned with pixel bounds should have already been turned into
101 // non-AA).
102 fClearCompatible = deviceQuadType == GrQuadType::kRect && aaType == GrAAType::kNone;
103 } else {
104 // Paint isn't clear compatible
105 fClearCompatible = false;
106 }
107
108 fWideColor = !SkPMColor4fFitsInBytes(paintColor);
109
110 // The color stored with the quad is the clear color if a scissor-clear is decided upon
111 // when executing the op.
Michael Ludwigc96fc372019-01-08 15:46:15 -0500112 fDeviceQuads.push_back(deviceQuad, deviceQuadType, { paintColor, edgeFlags });
113 fLocalQuads.push_back(localQuad, localQuadType);
114 this->setBounds(deviceQuad.bounds(deviceQuadType),
115 HasAABloat(aaType == GrAAType::kCoverage), IsZeroArea::kNo);
Michael Ludwig69858532018-11-28 15:34:34 -0500116 }
117
118 const char* name() const override { return "FillRectOp"; }
119
120 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
121 return fHelper.visitProxies(func);
122 }
123
124#ifdef SK_DEBUG
125 SkString dumpInfo() const override {
126 SkString str;
Michael Ludwigc96fc372019-01-08 15:46:15 -0500127 str.appendf("# draws: %u\n", this->quadCount());
Michael Ludwig69858532018-11-28 15:34:34 -0500128 str.appendf("Device quad type: %u, local quad type: %u\n",
Michael Ludwigc96fc372019-01-08 15:46:15 -0500129 (uint32_t) fDeviceQuads.quadType(), (uint32_t) fLocalQuads.quadType());
Michael Ludwig69858532018-11-28 15:34:34 -0500130 str += fHelper.dumpInfo();
Michael Ludwigc96fc372019-01-08 15:46:15 -0500131 GrPerspQuad device, local;
132 for (int i = 0; i < this->quadCount(); i++) {
133 device = fDeviceQuads[i];
134 const ColorAndAA& info = fDeviceQuads.metadata(i);
135 local = fLocalQuads[i];
136 str += dump_quad_info(i, device, local, info.fColor, info.fAAFlags);
Michael Ludwig69858532018-11-28 15:34:34 -0500137 }
138 str += INHERITED::dumpInfo();
139 return str;
140 }
141#endif
142
143 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
144 // Initialize aggregate color analysis with the first quad's color (which always exists)
Michael Ludwigc96fc372019-01-08 15:46:15 -0500145 SkASSERT(this->quadCount() > 0);
146 GrProcessorAnalysisColor quadColors(fDeviceQuads.metadata(0).fColor);
Michael Ludwig69858532018-11-28 15:34:34 -0500147 // Then combine the colors of any additional quads (e.g. from MakeSet)
Michael Ludwigc96fc372019-01-08 15:46:15 -0500148 for (int i = 1; i < this->quadCount(); ++i) {
149 quadColors = GrProcessorAnalysisColor::Combine(quadColors,
150 fDeviceQuads.metadata(i).fColor);
Michael Ludwigca91e1f2018-12-10 10:44:44 -0500151 if (quadColors.isUnknown()) {
152 // No point in accumulating additional starting colors, combining cannot make it
153 // less unknown.
154 break;
155 }
Michael Ludwig69858532018-11-28 15:34:34 -0500156 }
Michael Ludwig72ab3462018-12-10 12:43:36 -0500157
158 // If the AA type is coverage, it will be a single value per pixel; if it's not coverage AA
159 // then the coverage is always 1.0, so specify kNone for more optimal blending.
160 GrProcessorAnalysisCoverage coverage = fHelper.aaType() == GrAAType::kCoverage ?
161 GrProcessorAnalysisCoverage::kSingleChannel :
162 GrProcessorAnalysisCoverage::kNone;
163 auto result = fHelper.xpRequiresDstTexture(caps, clip, coverage, &quadColors);
Michael Ludwig69858532018-11-28 15:34:34 -0500164 // If there is a constant color after analysis, that means all of the quads should be set
165 // to the same color (even if they started out with different colors).
166 SkPMColor4f colorOverride;
167 if (quadColors.isConstant(&colorOverride)) {
Michael Ludwigc96fc372019-01-08 15:46:15 -0500168 for (int i = 0; i < this->quadCount(); ++i) {
169 fDeviceQuads.metadata(i).fColor = colorOverride;
Michael Ludwig69858532018-11-28 15:34:34 -0500170 }
171 }
172
173 return result;
174 }
175
176 FixedFunctionFlags fixedFunctionFlags() const override {
177 // Since the AA type of the whole primitive is kept consistent with the per edge AA flags
178 // the helper's fixed function flags are appropriate.
179 return fHelper.fixedFunctionFlags();
180 }
181
182 DEFINE_OP_CLASS_ID
183
184private:
185 // For GrFillRectOp::MakeSet's use of addQuad
Michael Ludwig69858532018-11-28 15:34:34 -0500186 friend std::unique_ptr<GrDrawOp> GrFillRectOp::MakeSet(GrContext* context, GrPaint&& paint,
187 GrAAType aaType, const SkMatrix& viewMatrix,
188 const GrRenderTargetContext::QuadSetEntry quads[], int quadCount,
189 const GrUserStencilSettings* stencilSettings);
190
Michael Ludwigc96fc372019-01-08 15:46:15 -0500191 void onPrepareDraws(Target* target) override {
Michael Ludwig69858532018-11-28 15:34:34 -0500192 TRACE_EVENT0("skia", TRACE_FUNC);
193
194 using Domain = GrQuadPerEdgeAA::Domain;
195 static constexpr SkRect kEmptyDomain = SkRect::MakeEmpty();
196
Michael Ludwigc96fc372019-01-08 15:46:15 -0500197 VertexSpec vertexSpec(fDeviceQuads.quadType(),
Michael Ludwig69858532018-11-28 15:34:34 -0500198 fWideColor ? ColorType::kHalf : ColorType::kByte,
Michael Ludwigc96fc372019-01-08 15:46:15 -0500199 fLocalQuads.quadType(), fHelper.usesLocalCoords(), Domain::kNo,
Michael Ludwig93aeba02018-12-21 09:50:31 -0500200 fHelper.aaType(), fHelper.compatibleWithAlphaAsCoverage());
Michael Ludwig69858532018-11-28 15:34:34 -0500201
Michael Ludwig467994d2018-12-03 14:58:31 +0000202 sk_sp<GrGeometryProcessor> gp = GrQuadPerEdgeAA::MakeProcessor(vertexSpec);
Michael Ludwig69858532018-11-28 15:34:34 -0500203 size_t vertexSize = gp->vertexStride();
204
205 const GrBuffer* vbuffer;
206 int vertexOffsetInBuffer = 0;
207
208 // Fill the allocated vertex data
Michael Ludwig93aeba02018-12-21 09:50:31 -0500209 void* vdata = target->makeVertexSpace(
Michael Ludwigc96fc372019-01-08 15:46:15 -0500210 vertexSize, this->quadCount() * vertexSpec.verticesPerQuad(),
Michael Ludwig93aeba02018-12-21 09:50:31 -0500211 &vbuffer, &vertexOffsetInBuffer);
Michael Ludwig69858532018-11-28 15:34:34 -0500212 if (!vdata) {
213 SkDebugf("Could not allocate vertices\n");
214 return;
215 }
216
217 // vertices pointer advances through vdata based on Tessellate's return value
218 void* vertices = vdata;
Michael Ludwigc96fc372019-01-08 15:46:15 -0500219 for (int i = 0; i < this->quadCount(); ++i) {
220 const GrPerspQuad& device = fDeviceQuads[i];
221 const ColorAndAA& info = fDeviceQuads.metadata(i);
222 const GrPerspQuad& local = fLocalQuads[i];
223
224 vertices = GrQuadPerEdgeAA::Tessellate(vertices, vertexSpec, device, info.fColor, local,
225 kEmptyDomain, info.fAAFlags);
Michael Ludwig69858532018-11-28 15:34:34 -0500226 }
227
228 // Configure the mesh for the vertex data
Michael Ludwig93aeba02018-12-21 09:50:31 -0500229 GrMesh* mesh = target->allocMeshes(1);
Michael Ludwigc96fc372019-01-08 15:46:15 -0500230 if (!GrQuadPerEdgeAA::ConfigureMeshIndices(target, mesh, vertexSpec, this->quadCount())) {
Michael Ludwig93aeba02018-12-21 09:50:31 -0500231 SkDebugf("Could not allocate indices\n");
232 return;
Michael Ludwig69858532018-11-28 15:34:34 -0500233 }
234 mesh->setVertexData(vbuffer, vertexOffsetInBuffer);
235
236 auto pipe = fHelper.makePipeline(target);
237 target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
238 }
239
240 CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
241 TRACE_EVENT0("skia", TRACE_FUNC);
242 const auto* that = t->cast<FillRectOp>();
243
Michael Ludwig93aeba02018-12-21 09:50:31 -0500244 if ((fHelper.aaType() == GrAAType::kCoverage ||
245 that->fHelper.aaType() == GrAAType::kCoverage) &&
Michael Ludwigc96fc372019-01-08 15:46:15 -0500246 this->quadCount() + that->quadCount() > GrQuadPerEdgeAA::kNumAAQuadsInIndexBuffer) {
Michael Ludwig93aeba02018-12-21 09:50:31 -0500247 // This limit on batch size seems to help on Adreno devices
248 return CombineResult::kCannotCombine;
249 }
250
Michael Ludwigc96fc372019-01-08 15:46:15 -0500251 // Unlike most users of the draw op helper, this op can merge none-aa and coverage-aa draw
252 // ops together, so pass true as the last argument.
Michael Ludwig69858532018-11-28 15:34:34 -0500253 if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds(), true)) {
254 return CombineResult::kCannotCombine;
255 }
256
257 // If the processor sets are compatible, the two ops are always compatible; it just needs
258 // to adjust the state of the op to be the more general quad and aa types of the two ops.
259
Michael Ludwig69858532018-11-28 15:34:34 -0500260 fClearCompatible &= that->fClearCompatible;
261 fWideColor |= that->fWideColor;
262
263 // The helper stores the aa type, but isCompatible(with true arg) allows the two ops' aa
264 // types to be none and coverage, in which case this op's aa type must be lifted to coverage
265 // so that quads with no aa edges can be batched with quads that have some/all edges aa'ed.
266 if (fHelper.aaType() == GrAAType::kNone && that->fHelper.aaType() == GrAAType::kCoverage) {
267 fHelper.setAAType(GrAAType::kCoverage);
268 }
269
Michael Ludwigc96fc372019-01-08 15:46:15 -0500270 fDeviceQuads.concat(that->fDeviceQuads);
271 fLocalQuads.concat(that->fLocalQuads);
Michael Ludwig69858532018-11-28 15:34:34 -0500272 return CombineResult::kMerged;
273 }
274
275 // Similar to onCombineIfPossible, but adds a quad assuming its op would have been compatible.
276 // But since it's avoiding the op list management, it must update the op's bounds. This is only
277 // used with quad sets, which uses the same view matrix for each quad so this assumes that the
278 // device quad type of the new quad is the same as the op's.
Michael Ludwigc96fc372019-01-08 15:46:15 -0500279 void addQuad(const GrPerspQuad& deviceQuad, const GrPerspQuad& localQuad,
280 GrQuadType localQuadType, const SkPMColor4f& color, GrQuadAAFlags edgeAA,
281 GrAAType aaType) {
282 SkASSERT(deviceQuad.quadType() <= fDeviceQuads.quadType());
Michael Ludwig69858532018-11-28 15:34:34 -0500283
284 // The new quad's aa type should be the same as the first quad's or none, except when the
285 // first quad's aa type was already downgraded to none, in which case the stored type must
286 // be lifted to back to the requested type.
287 if (aaType != fHelper.aaType()) {
288 if (aaType != GrAAType::kNone) {
289 // Original quad was downgraded to non-aa, lift back up to this quad's required type
290 SkASSERT(fHelper.aaType() == GrAAType::kNone);
291 fHelper.setAAType(aaType);
292 }
293 // else the new quad could have been downgraded but the other quads can't be, so don't
294 // reset the op's accumulated aa type.
295 }
296
Michael Ludwig69858532018-11-28 15:34:34 -0500297 // clear compatible won't need to be updated, since device quad type and paint is the same,
298 // but this quad has a new color, so maybe update wide color
Michael Ludwigc96fc372019-01-08 15:46:15 -0500299 fWideColor |= !SkPMColor4fFitsInBytes(color);
Michael Ludwig69858532018-11-28 15:34:34 -0500300
301 // Update the bounds and add the quad to this op's storage
302 SkRect newBounds = this->bounds();
Michael Ludwigc96fc372019-01-08 15:46:15 -0500303 newBounds.joinPossiblyEmptyRect(deviceQuad.bounds(fDeviceQuads.quadType()));
Michael Ludwig69858532018-11-28 15:34:34 -0500304 this->setBounds(newBounds, HasAABloat(fHelper.aaType() == GrAAType::kCoverage),
305 IsZeroArea::kNo);
Michael Ludwigc96fc372019-01-08 15:46:15 -0500306 fDeviceQuads.push_back(deviceQuad, fDeviceQuads.quadType(), { color, edgeAA });
307 fLocalQuads.push_back(localQuad, localQuadType);
Michael Ludwig69858532018-11-28 15:34:34 -0500308 }
309
Michael Ludwigc96fc372019-01-08 15:46:15 -0500310 int quadCount() const {
311 // Sanity check that the parallel arrays for quad properties all have the same size
312 SkASSERT(fDeviceQuads.count() == fLocalQuads.count());
313 return fDeviceQuads.count();
314 }
315
316 struct ColorAndAA {
317 SkPMColor4f fColor;
318 GrQuadAAFlags fAAFlags;
319 };
Michael Ludwig69858532018-11-28 15:34:34 -0500320
321 Helper fHelper;
Michael Ludwigc96fc372019-01-08 15:46:15 -0500322 GrTQuadList<ColorAndAA> fDeviceQuads;
323 // No metadata attached to the local quads
324 GrQuadList fLocalQuads;
Michael Ludwig69858532018-11-28 15:34:34 -0500325
Michael Ludwig69858532018-11-28 15:34:34 -0500326 unsigned fWideColor: 1;
327
328 // True if fQuad produced by a rectangle-preserving view matrix, is pixel aligned or non-AA,
329 // and its paint is a constant blended color.
330 unsigned fClearCompatible: 1;
331
332 typedef GrMeshDrawOp INHERITED;
333};
334
335} // anonymous namespace
336
337namespace GrFillRectOp {
338
Michael Ludwig72ab3462018-12-10 12:43:36 -0500339std::unique_ptr<GrDrawOp> MakePerEdge(GrContext* context,
340 GrPaint&& paint,
341 GrAAType aaType,
342 GrQuadAAFlags edgeAA,
343 const SkMatrix& viewMatrix,
344 const SkRect& rect,
345 const GrUserStencilSettings* stencilSettings) {
Michael Ludwig69858532018-11-28 15:34:34 -0500346 return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
347 GrPerspQuad(rect, viewMatrix), GrQuadTypeForTransformedRect(viewMatrix),
348 GrPerspQuad(rect, SkMatrix::I()), GrQuadType::kRect);
349}
350
Michael Ludwig72ab3462018-12-10 12:43:36 -0500351std::unique_ptr<GrDrawOp> MakePerEdgeWithLocalMatrix(GrContext* context,
352 GrPaint&& paint,
353 GrAAType aaType,
354 GrQuadAAFlags edgeAA,
355 const SkMatrix& viewMatrix,
356 const SkMatrix& localMatrix,
357 const SkRect& rect,
358 const GrUserStencilSettings* stencilSettings) {
Michael Ludwig69858532018-11-28 15:34:34 -0500359 GrQuadType localQuadType = GrQuadTypeForTransformedRect(localMatrix);
360 return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
361 GrPerspQuad(rect, viewMatrix), GrQuadTypeForTransformedRect(viewMatrix),
362 GrPerspQuad(rect, localMatrix), localQuadType);
363}
364
Michael Ludwig72ab3462018-12-10 12:43:36 -0500365std::unique_ptr<GrDrawOp> MakePerEdgeWithLocalRect(GrContext* context,
366 GrPaint&& paint,
367 GrAAType aaType,
368 GrQuadAAFlags edgeAA,
369 const SkMatrix& viewMatrix,
370 const SkRect& rect,
371 const SkRect& localRect,
372 const GrUserStencilSettings* stencilSettings) {
Michael Ludwig69858532018-11-28 15:34:34 -0500373 return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
374 GrPerspQuad(rect, viewMatrix), GrQuadTypeForTransformedRect(viewMatrix),
375 GrPerspQuad(localRect, SkMatrix::I()), GrQuadType::kRect);
376}
377
378std::unique_ptr<GrDrawOp> MakeSet(GrContext* context,
379 GrPaint&& paint,
380 GrAAType aaType,
381 const SkMatrix& viewMatrix,
382 const GrRenderTargetContext::QuadSetEntry quads[],
383 int cnt,
384 const GrUserStencilSettings* stencilSettings) {
385 // First make a draw op for the first quad in the set
386 SkASSERT(cnt > 0);
387 GrQuadType deviceQuadType = GrQuadTypeForTransformedRect(viewMatrix);
388
389 paint.setColor4f(quads[0].fColor);
390 std::unique_ptr<GrDrawOp> op = FillRectOp::Make(context, std::move(paint), aaType,
391 quads[0].fAAFlags, stencilSettings, GrPerspQuad(quads[0].fRect, viewMatrix),
392 deviceQuadType, GrPerspQuad(quads[0].fRect, quads[0].fLocalMatrix),
393 GrQuadTypeForTransformedRect(quads[0].fLocalMatrix));
394 auto* fillRects = op->cast<FillRectOp>();
395
396 // Accumulate remaining quads similar to onCombineIfPossible() without creating an op
397 for (int i = 1; i < cnt; ++i) {
398 GrPerspQuad deviceQuad(quads[i].fRect, viewMatrix);
399
400 GrAAType resolvedAA;
401 GrQuadAAFlags resolvedEdgeFlags;
402 GrResolveAATypeForQuad(aaType, quads[i].fAAFlags, deviceQuad, deviceQuadType,
403 &resolvedAA, &resolvedEdgeFlags);
404
Michael Ludwigc96fc372019-01-08 15:46:15 -0500405 fillRects->addQuad(deviceQuad, GrPerspQuad(quads[i].fRect, quads[i].fLocalMatrix),
406 GrQuadTypeForTransformedRect(quads[i].fLocalMatrix), quads[i].fColor,
407 resolvedEdgeFlags,resolvedAA);
Michael Ludwig69858532018-11-28 15:34:34 -0500408 }
409
410 return op;
411}
412
Michael Ludwig72ab3462018-12-10 12:43:36 -0500413std::unique_ptr<GrDrawOp> Make(GrContext* context,
414 GrPaint&& paint,
415 GrAAType aaType,
416 const SkMatrix& viewMatrix,
417 const SkRect& rect,
418 const GrUserStencilSettings* stencil) {
419 return MakePerEdge(context, std::move(paint), aaType,
420 aaType == GrAAType::kCoverage ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone,
421 viewMatrix, rect, stencil);
422}
423
424std::unique_ptr<GrDrawOp> MakeWithLocalMatrix(GrContext* context,
425 GrPaint&& paint,
426 GrAAType aaType,
427 const SkMatrix& viewMatrix,
428 const SkMatrix& localMatrix,
429 const SkRect& rect,
430 const GrUserStencilSettings* stencil) {
431 return MakePerEdgeWithLocalMatrix(context, std::move(paint), aaType,
432 aaType == GrAAType::kCoverage ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone,
433 viewMatrix, localMatrix, rect, stencil);
434}
435
436std::unique_ptr<GrDrawOp> MakeWithLocalRect(GrContext* context,
437 GrPaint&& paint,
438 GrAAType aaType,
439 const SkMatrix& viewMatrix,
440 const SkRect& rect,
441 const SkRect& localRect,
442 const GrUserStencilSettings* stencil) {
443 return MakePerEdgeWithLocalRect(context, std::move(paint), aaType,
444 aaType == GrAAType::kCoverage ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone,
445 viewMatrix, rect, localRect, stencil);
446}
447
Michael Ludwig69858532018-11-28 15:34:34 -0500448} // namespace GrFillRectOp
449
450#if GR_TEST_UTILS
451
452#include "GrDrawOpTest.h"
453#include "SkGr.h"
454
455GR_DRAW_OP_TEST_DEFINE(FillRectOp) {
456 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
457 SkRect rect = GrTest::TestRect(random);
458
459 GrAAType aaType = GrAAType::kNone;
460 if (random->nextBool()) {
461 aaType = (fsaaType == GrFSAAType::kUnifiedMSAA) ? GrAAType::kMSAA : GrAAType::kCoverage;
462 }
463 const GrUserStencilSettings* stencil = random->nextBool() ? nullptr
464 : GrGetRandomStencil(random, context);
465
466 GrQuadAAFlags aaFlags = GrQuadAAFlags::kNone;
467 aaFlags |= random->nextBool() ? GrQuadAAFlags::kLeft : GrQuadAAFlags::kNone;
468 aaFlags |= random->nextBool() ? GrQuadAAFlags::kTop : GrQuadAAFlags::kNone;
469 aaFlags |= random->nextBool() ? GrQuadAAFlags::kRight : GrQuadAAFlags::kNone;
470 aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone;
471
472 if (random->nextBool()) {
473 if (random->nextBool()) {
474 if (random->nextBool()) {
475 // Local matrix with a set op
476 uint32_t extraQuadCt = random->nextRangeU(1, 4);
477 SkTArray<GrRenderTargetContext::QuadSetEntry> quads(extraQuadCt + 1);
478 quads.push_back(
479 {rect, SkPMColor4f::FromBytes_RGBA(SkColorToPremulGrColor(random->nextU())),
480 GrTest::TestMatrixInvertible(random), aaFlags});
481 for (uint32_t i = 0; i < extraQuadCt; ++i) {
482 GrQuadAAFlags aaFlags = GrQuadAAFlags::kNone;
483 aaFlags |= random->nextBool() ? GrQuadAAFlags::kLeft : GrQuadAAFlags::kNone;
484 aaFlags |= random->nextBool() ? GrQuadAAFlags::kTop : GrQuadAAFlags::kNone;
485 aaFlags |= random->nextBool() ? GrQuadAAFlags::kRight : GrQuadAAFlags::kNone;
486 aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone;
487
488 quads.push_back(
489 {GrTest::TestRect(random),
490 SkPMColor4f::FromBytes_RGBA(SkColorToPremulGrColor(random->nextU())),
491 GrTest::TestMatrixInvertible(random), aaFlags});
492 }
493
494 return GrFillRectOp::MakeSet(context, std::move(paint), aaType, viewMatrix,
495 quads.begin(), quads.count(), stencil);
496 } else {
497 // Single local matrix
498 SkMatrix localMatrix = GrTest::TestMatrixInvertible(random);
Michael Ludwig72ab3462018-12-10 12:43:36 -0500499 return GrFillRectOp::MakePerEdgeWithLocalMatrix(context, std::move(paint), aaType,
500 aaFlags, viewMatrix, localMatrix,
501 rect, stencil);
Michael Ludwig69858532018-11-28 15:34:34 -0500502 }
503 } else {
504 // Pass local rect directly
505 SkRect localRect = GrTest::TestRect(random);
Michael Ludwig72ab3462018-12-10 12:43:36 -0500506 return GrFillRectOp::MakePerEdgeWithLocalRect(context, std::move(paint), aaType,
507 aaFlags, viewMatrix, rect, localRect,
508 stencil);
Michael Ludwig69858532018-11-28 15:34:34 -0500509 }
510 } else {
511 // The simplest constructor
Michael Ludwig72ab3462018-12-10 12:43:36 -0500512 return GrFillRectOp::MakePerEdge(context, std::move(paint), aaType, aaFlags, viewMatrix,
513 rect, stencil);
Michael Ludwig69858532018-11-28 15:34:34 -0500514 }
515}
516
517#endif