Flutter Engine
The Flutter Engine
FillRectOp.cpp
Go to the documentation of this file.
1/*
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
9
11#include "include/core/SkRect.h"
17#include "src/gpu/ganesh/SkGr.h"
27
28namespace {
29
33
34#if defined(GR_TEST_UTILS)
35SkString dump_quad_info(int index, const GrQuad* deviceQuad,
36 const GrQuad* localQuad, const SkPMColor4f& color,
37 GrQuadAAFlags aaFlags) {
38 GrQuad safeLocal = localQuad ? *localQuad : GrQuad();
39 SkString str;
40 str.appendf("%d: Color: [%.2f, %.2f, %.2f, %.2f], Edge AA: l%u_t%u_r%u_b%u, \n"
41 " device quad: [(%.2f, %2.f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), "
42 "(%.2f, %.2f, %.2f)],\n"
43 " local quad: [(%.2f, %2.f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), "
44 "(%.2f, %.2f, %.2f)]\n",
45 index, color.fR, color.fG, color.fB, color.fA,
46 (uint32_t) (aaFlags & GrQuadAAFlags::kLeft),
47 (uint32_t) (aaFlags & GrQuadAAFlags::kTop),
48 (uint32_t) (aaFlags & GrQuadAAFlags::kRight),
49 (uint32_t) (aaFlags & GrQuadAAFlags::kBottom),
50 deviceQuad->x(0), deviceQuad->y(0), deviceQuad->w(0),
51 deviceQuad->x(1), deviceQuad->y(1), deviceQuad->w(1),
52 deviceQuad->x(2), deviceQuad->y(2), deviceQuad->w(2),
53 deviceQuad->x(3), deviceQuad->y(3), deviceQuad->w(3),
54 safeLocal.x(0), safeLocal.y(0), safeLocal.w(0),
55 safeLocal.x(1), safeLocal.y(1), safeLocal.w(1),
56 safeLocal.x(2), safeLocal.y(2), safeLocal.w(2),
57 safeLocal.x(3), safeLocal.y(3), safeLocal.w(3));
58 return str;
59}
60#endif
61
62class FillRectOpImpl final : public GrMeshDrawOp {
63private:
65
66public:
67 static GrOp::Owner Make(GrRecordingContext* context,
68 GrPaint&& paint,
69 GrAAType aaType,
70 DrawQuad* quad,
71 const GrUserStencilSettings* stencilSettings,
72 Helper::InputFlags inputFlags) {
73 // Clean up deviations between aaType and edgeAA
75 &aaType, &quad->fEdgeFlags);
76 return Helper::FactoryHelper<FillRectOpImpl>(context, std::move(paint), aaType, quad,
77 stencilSettings, inputFlags);
78 }
79
80 // aaType is passed to Helper in the initializer list, so incongruities between aaType and
81 // edgeFlags must be resolved prior to calling this constructor.
82 FillRectOpImpl(GrProcessorSet* processorSet, SkPMColor4f paintColor, GrAAType aaType,
83 DrawQuad* quad, const GrUserStencilSettings* stencil,
84 Helper::InputFlags inputFlags)
85 : INHERITED(ClassID())
86 , fHelper(processorSet, aaType, stencil, inputFlags)
87 , fQuads(1, !fHelper.isTrivial()) {
88 // Set bounds before clipping so we don't have to worry about unioning the bounds of
89 // the two potential quads (GrQuad::bounds() is perspective-safe).
90 bool hairline = GrQuadUtils::WillUseHairline(quad->fDevice, aaType, quad->fEdgeFlags);
91 this->setBounds(quad->fDevice.bounds(), HasAABloat(aaType == GrAAType::kCoverage),
92 hairline ? IsHairline::kYes : IsHairline::kNo);
93 DrawQuad extra;
94 // Always crop to W>0 to remain consistent with GrQuad::bounds()
95 int count = GrQuadUtils::ClipToW0(quad, &extra);
96 if (count == 0) {
97 // We can't discard the op at this point, but disable AA flags so it won't go through
98 // inset/outset processing
100 count = 1;
101 }
102
103 // Conservatively keep track of the local coordinates; it may be that the paint doesn't
104 // need them after analysis is finished. If the paint is known to be solid up front they
105 // can be skipped entirely.
106 fQuads.append(quad->fDevice, {paintColor, quad->fEdgeFlags},
107 fHelper.isTrivial() ? nullptr : &quad->fLocal);
108 if (count > 1) {
109 fQuads.append(extra.fDevice, { paintColor, extra.fEdgeFlags },
110 fHelper.isTrivial() ? nullptr : &extra.fLocal);
111 }
112 }
113
114 const char* name() const override { return "FillRectOp"; }
115
116 void visitProxies(const GrVisitProxyFunc& func) const override {
117 if (fProgramInfo) {
118 fProgramInfo->visitFPProxies(func);
119 } else {
120 return fHelper.visitProxies(func);
121 }
122 }
123
125 GrClampType clampType) override {
126 // Initialize aggregate color analysis with the first quad's color (which always exists)
127 auto iter = fQuads.metadata();
128 SkAssertResult(iter.next());
129 GrProcessorAnalysisColor quadColors(iter->fColor);
130 // Then combine the colors of any additional quads (e.g. from MakeSet)
131 while(iter.next()) {
132 quadColors = GrProcessorAnalysisColor::Combine(quadColors, iter->fColor);
133 if (quadColors.isUnknown()) {
134 // No point in accumulating additional starting colors, combining cannot make it
135 // less unknown.
136 break;
137 }
138 }
139
140 // If the AA type is coverage, it will be a single value per pixel; if it's not coverage AA
141 // then the coverage is always 1.0, so specify kNone for more optimal blending.
142 auto coverage = fHelper.aaType() == GrAAType::kCoverage
145 auto result = fHelper.finalizeProcessors(caps, clip, clampType, coverage, &quadColors);
146 // If there is a constant color after analysis, that means all of the quads should be set
147 // to the same color (even if they started out with different colors).
148 iter = fQuads.metadata();
149 SkPMColor4f colorOverride;
150 if (quadColors.isConstant(&colorOverride)) {
152 while(iter.next()) {
153 iter->fColor = colorOverride;
154 }
155 } else {
156 // Otherwise compute the color type needed as the max over all quads.
158 while(iter.next()) {
161 }
162 }
163 // Most SkShaders' FPs multiply their calculated color by the paint color or alpha. We want
164 // to use ColorType::kNone to optimize out that multiply. However, if there are no color
165 // FPs then were really writing a special shader for white rectangles and not saving any
166 // multiples. So in that case use bytes to avoid the extra shader (and possibly work around
167 // an ANGLE issue: crbug.com/942565).
168 if (fColorType == ColorType::kNone && !result.hasColorFragmentProcessor()) {
170 }
171
172 return result;
173 }
174
175 FixedFunctionFlags fixedFunctionFlags() const override {
176 // Since the AA type of the whole primitive is kept consistent with the per edge AA flags
177 // the helper's fixed function flags are appropriate.
178 return fHelper.fixedFunctionFlags();
179 }
180
182
183private:
184 friend class skgpu::ganesh::FillRectOp; // for access to addQuad
185
186#if defined(GR_TEST_UTILS)
187 int numQuads() const final { return fQuads.count(); }
188#endif
189
190 VertexSpec vertexSpec() const {
192 fHelper.aaType(), fQuads.count());
193
194 return VertexSpec(fQuads.deviceQuadType(), fColorType, fQuads.localQuadType(),
195 fHelper.usesLocalCoords(), Subset::kNo, fHelper.aaType(),
196 fHelper.compatibleWithCoverageAsAlpha(), indexBufferOption);
197 }
198
199 GrProgramInfo* programInfo() override {
200 return fProgramInfo;
201 }
202
203 void onCreateProgramInfo(const GrCaps* caps,
204 SkArenaAlloc* arena,
205 const GrSurfaceProxyView& writeView,
206 bool usesMSAASurface,
207 GrAppliedClip&& appliedClip,
208 const GrDstProxyView& dstProxyView,
209 GrXferBarrierFlags renderPassXferBarriers,
210 GrLoadOp colorLoadOp) override {
211 const VertexSpec vertexSpec = this->vertexSpec();
212
214 SkASSERT(gp->vertexStride() == vertexSpec.vertexSize());
215
216 fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView, usesMSAASurface,
217 std::move(appliedClip),
218 dstProxyView, gp,
219 vertexSpec.primitiveType(),
220 renderPassXferBarriers, colorLoadOp);
221 }
222
224 const GrSurfaceProxyView& writeView,
226 const GrDstProxyView& dstProxyView,
227 GrXferBarrierFlags renderPassXferBarriers,
228 GrLoadOp colorLoadOp) override {
229 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
230
231 SkASSERT(!fPrePreparedVertices);
232
233 INHERITED::onPrePrepareDraws(rContext, writeView, clip, dstProxyView,
234 renderPassXferBarriers, colorLoadOp);
235
236 SkArenaAlloc* arena = rContext->priv().recordTimeAllocator();
237
238 const VertexSpec vertexSpec = this->vertexSpec();
239
240 const int totalNumVertices = fQuads.count() * vertexSpec.verticesPerQuad();
241 const size_t totalVertexSizeInBytes = vertexSpec.vertexSize() * totalNumVertices;
242
243 fPrePreparedVertices = arena->makeArrayDefault<char>(totalVertexSizeInBytes);
244
245 this->tessellate(vertexSpec, fPrePreparedVertices);
246 }
247
248 void tessellate(const VertexSpec& vertexSpec, char* dst) const {
249 static constexpr SkRect kEmptyDomain = SkRect::MakeEmpty();
250
251 skgpu::ganesh::QuadPerEdgeAA::Tessellator tessellator(vertexSpec, dst);
252 auto iter = fQuads.iterator();
253 while (iter.next()) {
254 // All entries should have local coords, or no entries should have local coords,
255 // matching !helper.isTrivial() (which is more conservative than helper.usesLocalCoords)
256 SkASSERT(iter.isLocalValid() != fHelper.isTrivial());
257 auto info = iter.metadata();
258 tessellator.append(iter.deviceQuad(), iter.localQuad(),
259 info.fColor, kEmptyDomain, info.fAAFlags);
260 }
261 }
262
263 void onPrepareDraws(GrMeshDrawTarget* target) override {
264 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
265
266 const VertexSpec vertexSpec = this->vertexSpec();
267
268 // Make sure that if the op thought it was a solid color, the vertex spec does not use
269 // local coords.
270 SkASSERT(!fHelper.isTrivial() || !fHelper.usesLocalCoords());
271
272 const int totalNumVertices = fQuads.count() * vertexSpec.verticesPerQuad();
273
274 // Fill the allocated vertex data
275 void* vdata = target->makeVertexSpace(vertexSpec.vertexSize(), totalNumVertices,
276 &fVertexBuffer, &fBaseVertex);
277 if (!vdata) {
278 SkDebugf("Could not allocate vertices\n");
279 return;
280 }
281
282 if (fPrePreparedVertices) {
283 const size_t totalVertexSizeInBytes = vertexSpec.vertexSize() * totalNumVertices;
284
285 memcpy(vdata, fPrePreparedVertices, totalVertexSizeInBytes);
286 } else {
287 this->tessellate(vertexSpec, (char*) vdata);
288 }
289
290 if (vertexSpec.needsIndexBuffer()) {
292 target, vertexSpec.indexBufferOption());
293 if (!fIndexBuffer) {
294 SkDebugf("Could not allocate indices\n");
295 return;
296 }
297 }
298 }
299
300 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
301 if (!fVertexBuffer) {
302 return;
303 }
304
305 const VertexSpec vertexSpec = this->vertexSpec();
306
307 if (vertexSpec.needsIndexBuffer() && !fIndexBuffer) {
308 return;
309 }
310
311 if (!fProgramInfo) {
312 this->createProgramInfo(flushState);
313 }
314
315 const int totalNumVertices = fQuads.count() * vertexSpec.verticesPerQuad();
316
317 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
318 flushState->bindBuffers(std::move(fIndexBuffer), nullptr, std::move(fVertexBuffer));
319 flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
321 flushState->opsRenderPass(),
322 vertexSpec,
323 0,
324 fQuads.count(),
325 totalNumVertices,
326 fBaseVertex);
327 }
328
329 CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) override {
330 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
331 auto that = t->cast<FillRectOpImpl>();
332
333 bool upgradeToCoverageAAOnMerge = false;
334 if (fHelper.aaType() != that->fHelper.aaType()) {
335 if (!CanUpgradeAAOnMerge(fHelper.aaType(), that->fHelper.aaType())) {
337 }
338 upgradeToCoverageAAOnMerge = true;
339 }
340
341 if (CombinedQuadCountWillOverflow(fHelper.aaType(), upgradeToCoverageAAOnMerge,
342 fQuads.count() + that->fQuads.count())) {
344 }
345
346 // Unlike most users of the draw op helper, this op can merge none-aa and coverage-aa draw
347 // ops together, so pass true as the last argument.
348 if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds(), true)) {
350 }
351
352 // If the paints were compatible, the trivial/solid-color state should be the same
353 SkASSERT(fHelper.isTrivial() == that->fHelper.isTrivial());
354
355 // If the processor sets are compatible, the two ops are always compatible; it just needs to
356 // adjust the state of the op to be the more general quad and aa types of the two ops and
357 // then concatenate the per-quad data.
358 fColorType = std::max(fColorType, that->fColorType);
359
360 // The helper stores the aa type, but isCompatible(with true arg) allows the two ops' aa
361 // types to be none and coverage, in which case this op's aa type must be lifted to coverage
362 // so that quads with no aa edges can be batched with quads that have some/all edges aa'ed.
363 if (upgradeToCoverageAAOnMerge) {
365 }
366
367 fQuads.concat(that->fQuads);
369 }
370
371#if defined(GR_TEST_UTILS)
372 SkString onDumpInfo() const override {
373 SkString str = SkStringPrintf("# draws: %d\n", fQuads.count());
374 str.appendf("Device quad type: %u, local quad type: %u\n",
375 (uint32_t) fQuads.deviceQuadType(), (uint32_t) fQuads.localQuadType());
376 str += fHelper.dumpInfo();
377 int i = 0;
378 auto iter = fQuads.iterator();
379 while(iter.next()) {
380 const ColorAndAA& info = iter.metadata();
381 str += dump_quad_info(i, iter.deviceQuad(), iter.localQuad(),
382 info.fColor, info.fAAFlags);
383 i++;
384 }
385 return str;
386 }
387#endif
388
389 bool canAddQuads(int numQuads, GrAAType aaType) {
390 // The new quad's aa type should be the same as the first quad's or none, except when the
391 // first quad's aa type was already downgraded to none, in which case the stored type must
392 // be lifted to back to the requested type.
393 int quadCount = fQuads.count() + numQuads;
394 if (aaType != fHelper.aaType() && aaType != GrAAType::kNone) {
395 auto indexBufferOption =
397 if (quadCount > skgpu::ganesh::QuadPerEdgeAA::QuadLimit(indexBufferOption)) {
398 // Promoting to the new aaType would've caused an overflow of the indexBuffer
399 // limit
400 return false;
401 }
402
403 // Original quad was downgraded to non-aa, lift back up to this quad's required type
404 SkASSERT(fHelper.aaType() == GrAAType::kNone);
405 fHelper.setAAType(aaType);
406 } else {
408 fHelper.aaType(), quadCount);
409 if (quadCount > skgpu::ganesh::QuadPerEdgeAA::QuadLimit(indexBufferOption)) {
410 return false; // This op can't grow any more
411 }
412 }
413
414 return true;
415 }
416
417 // Similar to onCombineIfPossible, but adds a quad assuming its op would have been compatible.
418 // But since it's avoiding the op list management, it must update the op's bounds.
419 bool addQuad(DrawQuad* quad, const SkPMColor4f& color, GrAAType aaType) {
420 SkRect newBounds = this->bounds();
421 newBounds.joinPossiblyEmptyRect(quad->fDevice.bounds());
422
423 DrawQuad extra;
424 int count = quad->fEdgeFlags != GrQuadAAFlags::kNone ? GrQuadUtils::ClipToW0(quad, &extra)
425 : 1;
426 if (count == 0 ) {
427 // Just skip the append (trivial success)
428 return true;
429 } else if (!this->canAddQuads(count, aaType)) {
430 // Not enough room in the index buffer for the AA type
431 return false;
432 } else {
433 // Can actually add the 1 or 2 quads representing the draw
434 fQuads.append(quad->fDevice, { color, quad->fEdgeFlags },
435 fHelper.isTrivial() ? nullptr : &quad->fLocal);
436 if (count > 1) {
437 fQuads.append(extra.fDevice, { color, extra.fEdgeFlags },
438 fHelper.isTrivial() ? nullptr : &extra.fLocal);
439 }
440 // Update the bounds
441 this->setBounds(newBounds, HasAABloat(fHelper.aaType() == GrAAType::kCoverage),
442 IsHairline::kNo);
443 return true;
444 }
445 }
446
447 struct ColorAndAA {
448 SkPMColor4f fColor;
449 GrQuadAAFlags fAAFlags;
450 };
451
452 Helper fHelper;
454 char* fPrePreparedVertices = nullptr;
455
456 GrProgramInfo* fProgramInfo = nullptr;
458
461 int fBaseVertex;
462
463 using INHERITED = GrMeshDrawOp;
464};
465
466} // anonymous namespace
467
468namespace skgpu::ganesh {
469
471 GrPaint&& paint,
472 GrAAType aaType,
473 DrawQuad* quad,
474 const GrUserStencilSettings* stencil,
475 InputFlags inputFlags) {
476 return FillRectOpImpl::Make(context, std::move(paint), aaType, std::move(quad), stencil,
477 inputFlags);
478}
479
481 GrPaint&& paint,
482 const SkMatrix& view,
483 const SkRect& rect,
484 const GrUserStencilSettings* stencil) {
486 return FillRectOpImpl::Make(context, std::move(paint), GrAAType::kNone, &quad, stencil,
488}
489
490GrOp::Owner FillRectOp::MakeOp(GrRecordingContext* context,
491 GrPaint&& paint,
492 GrAAType aaType,
493 const SkMatrix& viewMatrix,
494 const GrQuadSetEntry quads[],
495 int cnt,
496 const GrUserStencilSettings* stencilSettings,
497 int* numConsumed) {
498 // First make a draw op for the first quad in the set
499 SkASSERT(cnt > 0);
500
501 DrawQuad quad{GrQuad::MakeFromRect(quads[0].fRect, viewMatrix),
502 GrQuad::MakeFromRect(quads[0].fRect, quads[0].fLocalMatrix),
503 quads[0].fAAFlags};
504 paint.setColor4f(quads[0].fColor);
505 GrOp::Owner op = FillRectOp::Make(context, std::move(paint), aaType,
506 &quad, stencilSettings, InputFlags::kNone);
507 auto fillRects = op->cast<FillRectOpImpl>();
508
509 *numConsumed = 1;
510 // Accumulate remaining quads similar to onCombineIfPossible() without creating an op
511 for (int i = 1; i < cnt; ++i) {
512 quad = {GrQuad::MakeFromRect(quads[i].fRect, viewMatrix),
513 GrQuad::MakeFromRect(quads[i].fRect, quads[i].fLocalMatrix),
514 quads[i].fAAFlags};
515
516 GrAAType resolvedAA;
517 GrQuadUtils::ResolveAAType(aaType, quads[i].fAAFlags, quad.fDevice,
518 &resolvedAA, &quad.fEdgeFlags);
519
520 if (!fillRects->addQuad(&quad, quads[i].fColor, resolvedAA)) {
521 break;
522 }
523
524 (*numConsumed)++;
525 }
526
527 return op;
528}
529
531 const GrClip* clip,
532 GrRecordingContext* context,
533 GrPaint&& paint,
534 GrAAType aaType,
535 const SkMatrix& viewMatrix,
536 const GrQuadSetEntry quads[],
537 int cnt,
538 const GrUserStencilSettings* stencilSettings) {
539 int offset = 0;
540 int numLeft = cnt;
541 while (numLeft) {
542 int numConsumed = 0;
543
544 GrOp::Owner op = MakeOp(context, GrPaint::Clone(paint), aaType, viewMatrix,
545 &quads[offset], numLeft, stencilSettings,
546 &numConsumed);
547
548 offset += numConsumed;
549 numLeft -= numConsumed;
550
551 sdc->addDrawOp(clip, std::move(op));
552 }
553
554 SkASSERT(offset == cnt);
555}
556
557} // namespace skgpu::ganesh
558
559#if defined(GR_TEST_UTILS)
560
561uint32_t skgpu::ganesh::FillRectOp::ClassID() { return FillRectOpImpl::ClassID(); }
562
564#include "src/gpu/ganesh/SkGr.h"
565
566GR_DRAW_OP_TEST_DEFINE(FillRectOp) {
567 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
568 SkRect rect = GrTest::TestRect(random);
569
570 GrAAType aaType = GrAAType::kNone;
571 if (random->nextBool()) {
572 aaType = (numSamples > 1) ? GrAAType::kMSAA : GrAAType::kCoverage;
573 }
574 const GrUserStencilSettings* stencil = random->nextBool() ? nullptr
575 : GrGetRandomStencil(random, context);
576
578 aaFlags |= random->nextBool() ? GrQuadAAFlags::kLeft : GrQuadAAFlags::kNone;
579 aaFlags |= random->nextBool() ? GrQuadAAFlags::kTop : GrQuadAAFlags::kNone;
580 aaFlags |= random->nextBool() ? GrQuadAAFlags::kRight : GrQuadAAFlags::kNone;
581 aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone;
582
583 if (random->nextBool()) {
584 if (random->nextBool()) {
585 // Single local matrix
586 SkMatrix localMatrix = GrTest::TestMatrixInvertible(random);
587 DrawQuad quad = {GrQuad::MakeFromRect(rect, viewMatrix),
588 GrQuad::MakeFromRect(rect, localMatrix), aaFlags};
590 context, std::move(paint), aaType, &quad, stencil);
591 } else {
592 // Pass local rect directly
593 SkRect localRect = GrTest::TestRect(random);
594 DrawQuad quad = {GrQuad::MakeFromRect(rect, viewMatrix),
595 GrQuad(localRect), aaFlags};
597 context, std::move(paint), aaType, &quad, stencil);
598 }
599 } else {
600 // The simplest constructor
601 DrawQuad quad = {GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(rect), aaFlags};
602 return skgpu::ganesh::FillRectOp::Make(context, std::move(paint), aaType, &quad, stencil);
603 }
604}
605
606#endif
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
skgpu::ganesh::QuadPerEdgeAA::VertexSpec VertexSpec
SkRect fRect
Definition: FillRRectOp.cpp:73
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
int count
Definition: FontMgrTest.cpp:50
#define DEFINE_OP_CLASS_ID
Definition: GrOp.h:64
GrClampType
Definition: GrTypesPriv.h:228
GrQuadAAFlags
Definition: GrTypesPriv.h:247
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
Definition: GrTypesPriv.h:943
GrAAType
Definition: GrTypesPriv.h:200
GrLoadOp
Definition: GrTypesPriv.h:155
GrXferBarrierFlags
SkColorType fColorType
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
sk_sp< const GrBuffer > fIndexBuffer
sk_sp< const GrBuffer > fVertexBuffer
Definition: GrCaps.h:57
Definition: GrClip.h:29
friend class GrSimpleMeshDrawOpHelperWithStencil
Definition: GrDrawOp.h:119
virtual FixedFunctionFlags fixedFunctionFlags() const
Definition: GrDrawOp.h:112
virtual GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType)=0
size_t vertexStride() const
virtual GrProgramInfo * programInfo()=0
void createProgramInfo(const GrCaps *caps, SkArenaAlloc *arena, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&appliedClip, const GrDstProxyView &dstProxyView, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
Definition: GrMeshDrawOp.h:39
GrMeshDrawOp(uint32_t classID)
virtual void onPrePrepareDraws(GrRecordingContext *, const GrSurfaceProxyView &writeView, GrAppliedClip *, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
virtual void onCreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)=0
virtual void onPrepareDraws(GrMeshDrawTarget *)=0
static bool CanUpgradeAAOnMerge(GrAAType aa1, GrAAType aa2)
Definition: GrMeshDrawOp.h:31
static bool CombinedQuadCountWillOverflow(GrAAType aaType, bool willBeUpgradedToAA, int combinedQuadCount)
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindBuffers(sk_sp< const GrBuffer > indexBuffer, sk_sp< const GrBuffer > instanceBuffer, sk_sp< const GrBuffer > vertexBuffer, GrPrimitiveRestart primitiveRestart=GrPrimitiveRestart::kNo)
const GrCaps & caps() const final
GrOpsRenderPass * opsRenderPass()
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
Definition: GrOp.h:70
virtual void onExecute(GrOpFlushState *, const SkRect &chainBounds)=0
static Owner Make(GrRecordingContext *context, Args &&... args)
Definition: GrOp.h:75
std::unique_ptr< GrOp > Owner
Definition: GrOp.h:72
HasAABloat
Definition: GrOp.h:266
virtual const char * name() const =0
const T & cast() const
Definition: GrOp.h:148
const SkRect & bounds() const
Definition: GrOp.h:122
virtual void visitProxies(const GrVisitProxyFunc &) const
Definition: GrOp.h:95
void setBounds(const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
Definition: GrOp.h:279
virtual CombineResult onCombineIfPossible(GrOp *, SkArenaAlloc *, const GrCaps &)
Definition: GrOp.h:305
static GrPaint Clone(const GrPaint &src)
Definition: GrPaint.h:45
static GrProcessorAnalysisColor Combine(const GrProcessorAnalysisColor &a, const GrProcessorAnalysisColor &b)
const GrPipeline & pipeline() const
Definition: GrProgramInfo.h:39
const GrGeometryProcessor & geomProc() const
Definition: GrProgramInfo.h:40
void visitFPProxies(const GrVisitProxyFunc &func) const
Definition: GrProgramInfo.h:64
Definition: GrQuad.h:30
float y(int i) const
Definition: GrQuad.h:109
static GrQuad MakeFromRect(const SkRect &, const SkMatrix &)
Definition: GrQuad.cpp:107
float w(int i) const
Definition: GrQuad.h:110
float x(int i) const
Definition: GrQuad.h:108
SkRect bounds() const
Definition: GrQuad.h:81
SkArenaAlloc * recordTimeAllocator()
GrRecordingContextPriv priv()
GrSimpleMeshDrawOpHelper::InputFlags InputFlags
GrProcessorSet::Analysis finalizeProcessors(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor *geometryColor)
void visitProxies(const GrVisitProxyFunc &func) const
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const
bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil &that, const GrCaps &, const SkRect &thisBounds, const SkRect &thatBounds, bool ignoreAAType=false) const
GrProgramInfo * createProgramInfoWithStencil(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrGeometryProcessor *, GrPrimitiveType, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
T * makeArrayDefault(size_t count)
Definition: SkArenaAlloc.h:171
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:550
static GrOp::Owner Make(GrRecordingContext *, GrPaint &&, GrAAType, DrawQuad *, const GrUserStencilSettings *=nullptr, InputFlags=InputFlags::kNone)
Definition: FillRectOp.cpp:470
static void AddFillRectOps(SurfaceDrawContext *, const GrClip *, GrRecordingContext *, GrPaint &&, GrAAType, const SkMatrix &viewMatrix, const GrQuadSetEntry quads[], int quadCount, const GrUserStencilSettings *=nullptr)
Definition: FillRectOp.cpp:530
static GrOp::Owner MakeNonAARect(GrRecordingContext *, GrPaint &&, const SkMatrix &view, const SkRect &, const GrUserStencilSettings *=nullptr)
Definition: FillRectOp.cpp:480
void addDrawOp(const GrClip *, GrOp::Owner, const std::function< WillAddOpFn > &=std::function< WillAddOpFn >())
const Paint & paint
Definition: color_source.cc:38
DlColor color
GAsyncResult * result
uint32_t * target
static float max(float r, float g, float b)
Definition: hsl.cpp:49
bool WillUseHairline(const GrQuad &quad, GrAAType aaType, GrQuadAAFlags edgeFlags)
void ResolveAAType(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags, const GrQuad &quad, GrAAType *outAAType, GrQuadAAFlags *outEdgeFlags)
int ClipToW0(DrawQuad *quad, DrawQuad *extraVertices)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
void Helper(uword arg)
@ kNone
Definition: layer.h:53
dst
Definition: cp.py:12
int QuadLimit(IndexBufferOption option)
GrGeometryProcessor * MakeProcessor(SkArenaAlloc *arena, const VertexSpec &spec)
IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads)
ColorType MinColorType(SkPMColor4f color)
sk_sp< const GrBuffer > GetIndexBuffer(GrMeshDrawTarget *target, IndexBufferOption indexBufferOption)
void IssueDraw(const GrCaps &caps, GrOpsRenderPass *renderPass, const VertexSpec &spec, int runningQuadCount, int quadsInDraw, int maxVerts, int absVertBufferOffset)
SeparatedVector2 offset
GrQuad fLocal
Definition: GrQuad.h:186
GrQuad fDevice
Definition: GrQuad.h:185
GrQuadAAFlags fEdgeFlags
Definition: GrQuad.h:187
GrQuadAAFlags fAAFlags
Definition: GrOpsTypes.h:22
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595
void joinPossiblyEmptyRect(const SkRect &r)
Definition: SkRect.h:1174
IndexBufferOption indexBufferOption() const
Definition: QuadPerEdgeAA.h:88
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131