Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Device.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 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 */
8
20#include "include/core/SkM44.h"
22#include "include/core/SkMesh.h"
24#include "include/core/SkPath.h"
30#include "include/core/SkRect.h"
34#include "include/core/SkSize.h"
35#include "include/core/SkSpan.h"
46#include "include/gpu/GrTypes.h"
53#include "include/private/chromium/Slug.h" // IWYU pragma: keep
55#include "src/base/SkTLazy.h"
56#include "src/core/SkDevice.h"
57#include "src/core/SkDrawBase.h"
58#include "src/core/SkImageFilterTypes.h" // IWYU pragma: keep
61#include "src/core/SkMeshPriv.h"
68#include "src/gpu/Swizzle.h"
92#include "src/gpu/ganesh/SkGr.h"
102#include "src/text/GlyphRun.h"
105
106#include <atomic>
107#include <cstddef>
108#include <cstdint>
109#include <functional>
110#include <memory>
111#include <tuple>
112#include <utility>
113
115struct GrShaderCaps;
116struct SkDrawShadowRec;
117
118using namespace skia_private;
119
120#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(fContext->priv().singleOwner())
121
122#if defined(GR_TEST_UTILS)
123// GrContextOptions::fMaxTextureSizeOverride exists but doesn't allow for changing the
124// maxTextureSize on the fly.
125int gOverrideMaxTextureSizeGanesh = 0;
126// Allows tests to check how many tiles were drawn on the most recent call to
127// Device::drawAsTiledImageRect. This is an atomic because we can write to it from
128// multiple threads during "normal" operations. However, the tests that actually
129// read from it are done single-threaded.
130std::atomic<int> gNumTilesDrawnGanesh{0};
131#endif
132
133///////////////////////////////////////////////////////////////////////////////
134
135namespace {
136
137bool force_aa_clip(const skgpu::ganesh::SurfaceDrawContext* sdc) {
138 return sdc->numSamples() > 1 || sdc->alwaysAntialias();
139}
140
141inline GrPrimitiveType point_mode_to_primitive_type(SkCanvas::PointMode mode) {
142 switch (mode) {
149 }
150 SK_ABORT("Unexpected mode");
151}
152
153std::unique_ptr<GrFragmentProcessor> make_inverse_rrect_fp(const SkMatrix& viewMatrix,
154 const SkRRect& rrect, GrAA aa,
155 const GrShaderCaps& shaderCaps) {
156 SkTCopyOnFirstWrite<SkRRect> devRRect(rrect);
157 if (viewMatrix.isIdentity() || rrect.transform(viewMatrix, devRRect.writable())) {
158 auto edgeType = (aa == GrAA::kYes) ? GrClipEdgeType::kInverseFillAA
160 auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr, edgeType, *devRRect,
161 shaderCaps);
162 return (success) ? std::move(fp) : nullptr;
163 }
164 return nullptr;
165}
166
167bool init_vertices_paint(GrRecordingContext* rContext,
168 const GrColorInfo& colorInfo,
169 const SkPaint& skPaint,
170 const SkMatrix& ctm,
171 SkBlender* blender,
172 bool hasColors,
173 const SkSurfaceProps& props,
174 GrPaint* grPaint) {
175 if (hasColors) {
176 return SkPaintToGrPaintWithBlend(rContext,
177 colorInfo,
178 skPaint,
179 ctm,
180 blender,
181 props,
182 grPaint);
183 } else {
184 return SkPaintToGrPaint(rContext, colorInfo, skPaint, ctm, props, grPaint);
185 }
186}
187
188bool init_mesh_child_effects(GrRecordingContext* rContext,
189 const GrColorInfo& colorInfo,
190 const SkSurfaceProps& surfaceProps,
191 const SkMesh& mesh,
192 TArray<std::unique_ptr<GrFragmentProcessor>>* meshChildFPs) {
193 // We use `Scope::kRuntimeEffect` here to ensure that mesh shaders get the same "raw" sampling
194 // behavior from alpha-only image shaders as a Runtime Effect would, rather than the unexpected
195 // tinting-by-input-color.
196 GrFPArgs fpArgs(rContext, &colorInfo, surfaceProps, GrFPArgs::Scope::kRuntimeEffect);
197
198 for (const SkRuntimeEffect::ChildPtr& child : mesh.children()) {
199 auto [success, childFP] = GrFragmentProcessors::MakeChildFP(child, fpArgs);
200 if (!success) {
201 return false;
202 }
203 meshChildFPs->push_back(std::move(childFP));
204 }
205 return true;
206}
207
208} // anonymous namespace
209
210namespace skgpu::ganesh {
211
215 sk_sp<SkColorSpace> colorSpace,
216 GrSurfaceOrigin origin,
217 const SkSurfaceProps& surfaceProps,
218 InitContents init) {
219 auto sdc = SurfaceDrawContext::Make(rContext,
220 colorType,
221 std::move(proxy),
222 std::move(colorSpace),
223 origin,
225
226 return Device::Make(std::move(sdc), kPremul_SkAlphaType, init);
227}
228
229SkImageInfo Device::MakeInfo(SurfaceContext* sc, DeviceFlags flags) {
231 return SkImageInfo::Make(sc->width(), sc->height(), colorType,
232 flags & DeviceFlags::kIsOpaque ? kOpaque_SkAlphaType
234 sc->colorInfo().refColorSpace());
235}
236
237
238/** Checks that the alpha type is legal and gets constructor flags. Returns false if device creation
239 should fail. */
240bool Device::CheckAlphaTypeAndGetFlags(SkAlphaType alphaType,
241 InitContents init,
242 DeviceFlags* flags) {
243 *flags = DeviceFlags::kNone;
244 switch (alphaType) {
246 break;
248 *flags |= DeviceFlags::kIsOpaque;
249 break;
250 default: // If it is unpremul or unknown don't try to render
251 return false;
252 }
253 if (InitContents::kClear == init) {
254 *flags |= DeviceFlags::kNeedClear;
255 }
256 return true;
257}
258
259sk_sp<Device> Device::Make(std::unique_ptr<SurfaceDrawContext> sdc,
260 SkAlphaType alphaType,
261 InitContents init) {
262 if (!sdc) {
263 return nullptr;
264 }
265
266 GrRecordingContext* rContext = sdc->recordingContext();
267 if (rContext->abandoned()) {
268 return nullptr;
269 }
270
271 SkColorType ct = GrColorTypeToSkColorType(sdc->colorInfo().colorType());
272
273 DeviceFlags flags;
274 if (!rContext->colorTypeSupportedAsSurface(ct) ||
275 !CheckAlphaTypeAndGetFlags(alphaType, init, &flags)) {
276 return nullptr;
277 }
278 return sk_sp<Device>(new Device(std::move(sdc), flags));
279}
280
282 skgpu::Budgeted budgeted,
283 const SkImageInfo& ii,
284 SkBackingFit fit,
285 int sampleCount,
286 skgpu::Mipmapped mipmapped,
287 GrProtected isProtected,
288 GrSurfaceOrigin origin,
289 const SkSurfaceProps& props,
290 InitContents init) {
291 if (!rContext) {
292 return nullptr;
293 }
294
295 auto sdc = SurfaceDrawContext::Make(rContext,
297 ii.refColorSpace(),
298 fit,
299 ii.dimensions(),
300 props,
301 /*label=*/"MakeDevice",
302 sampleCount,
303 mipmapped,
304 isProtected,
305 origin,
306 budgeted);
307
308 return Device::Make(std::move(sdc), ii.alphaType(), init);
309}
310
311Device::Device(std::unique_ptr<SurfaceDrawContext> sdc, DeviceFlags flags)
312 : SkDevice(MakeInfo(sdc.get(), flags), sdc->surfaceProps())
313 , fContext(sk_ref_sp(sdc->recordingContext()))
314 , fSDFTControl(sdc->recordingContext()->priv().getSDFTControl(
315 sdc->surfaceProps().isUseDeviceIndependentFonts()))
316 , fSurfaceDrawContext(std::move(sdc))
317 , fClip(SkIRect::MakeSize(fSurfaceDrawContext->dimensions()),
318 &this->localToDevice(),
319 force_aa_clip(fSurfaceDrawContext.get())) {
320 if (flags & DeviceFlags::kNeedClear) {
321 this->clearAll();
322 }
323}
324
325Device::~Device() = default;
326
327///////////////////////////////////////////////////////////////////////////////
328
329bool Device::onReadPixels(const SkPixmap& pm, int x, int y) {
331
332 // Context TODO: Elevate direct context requirement to public API
333 auto dContext = fContext->asDirectContext();
334 if (!dContext || !SkImageInfoValidConversion(pm.info(), this->imageInfo())) {
335 return false;
336 }
337
338 return fSurfaceDrawContext->readPixels(dContext, pm, {x, y});
339}
340
341bool Device::onWritePixels(const SkPixmap& pm, int x, int y) {
343
344 // Context TODO: Elevate direct context requirement to public API
345 auto dContext = fContext->asDirectContext();
346 if (!dContext || !SkImageInfoValidConversion(this->imageInfo(), pm.info())) {
347 return false;
348 }
349
350 return fSurfaceDrawContext->writePixels(dContext, pm, {x, y});
351}
352
355 return false;
356}
357
360 return fSurfaceDrawContext.get();
361}
362
365 return fSurfaceDrawContext.get();
366}
367
370 return fSurfaceDrawContext.get();
371}
372
375 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "clearAll", fContext.get());
376
377 SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
378 fSurfaceDrawContext->clearAtLeast(rect, SK_PMColor4fTRANSPARENT);
379}
380
381///////////////////////////////////////////////////////////////////////////////
382
383void Device::clipPath(const SkPath& path, SkClipOp op, bool aa) {
384#if defined(GR_TEST_UTILS)
385 if (fContext->priv().options().fAllPathsVolatile && !path.isVolatile()) {
386 this->clipPath(SkPath(path).setIsVolatile(true), op, aa);
387 return;
388 }
389#endif
391 fClip.clipPath(this->localToDevice(), path, GrAA(aa), op);
392}
393
394void Device::clipRegion(const SkRegion& globalRgn, SkClipOp op) {
396
397 // Regions don't actually need AA, but in DMSAA mode every clip element is antialiased.
398 GrAA aa = GrAA(fSurfaceDrawContext->alwaysAntialias());
399
400 if (globalRgn.isEmpty()) {
401 fClip.clipRect(SkMatrix::I(), SkRect::MakeEmpty(), aa, op);
402 } else if (globalRgn.isRect()) {
403 fClip.clipRect(this->globalToDevice().asM33(), SkRect::Make(globalRgn.getBounds()), aa, op);
404 } else {
405 SkPath path;
406 globalRgn.getBoundaryPath(&path);
407 fClip.clipPath(this->globalToDevice().asM33(), path, aa, op);
408 }
409}
410
413 // Assume wide open and then perform intersect/difference operations reducing the region
414 region->setRect(bounds);
415 const SkRegion deviceBounds(bounds);
416 for (const ClipStack::Element& e : fClip) {
417 SkRegion tmp;
418 if (e.fShape.isRect() && e.fLocalToDevice.isIdentity()) {
419 tmp.setRect(e.fShape.rect().roundOut());
420 } else {
421 SkPath tmpPath;
422 e.fShape.asPath(&tmpPath);
423 tmpPath.transform(e.fLocalToDevice);
424 tmp.setPath(tmpPath, deviceBounds);
425 }
426
427 region->op(tmp, (SkRegion::Op) e.fOp);
428 }
429}
430
432 for (const ClipStack::Element& e : fClip) {
433 if (e.fAA == GrAA::kYes) {
434 return true;
435 }
436 SkASSERT(!fSurfaceDrawContext->alwaysAntialias());
437 }
438 return false;
439}
440
441///////////////////////////////////////////////////////////////////////////////
442
445 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawPaint", fContext.get());
446
447 GrPaint grPaint;
449 fSurfaceDrawContext->colorInfo(),
450 paint,
451 this->localToDevice(),
452 fSurfaceDrawContext->surfaceProps(),
453 &grPaint)) {
454 return;
455 }
456
457 fSurfaceDrawContext->drawPaint(this->clip(), std::move(grPaint), this->localToDevice());
458}
459
461 size_t count,
462 const SkPoint pts[],
463 const SkPaint& paint) {
465 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawPoints", fContext.get());
466 SkScalar width = paint.getStrokeWidth();
467 if (width < 0) {
468 return;
469 }
470
471 GrAA aa = fSurfaceDrawContext->chooseAA(paint);
472
473 if (count == 2 && mode == SkCanvas::kLines_PointMode) {
474 if (paint.getPathEffect()) {
475 // Probably a dashed line. Draw as a path.
476 GrPaint grPaint;
478 fSurfaceDrawContext->colorInfo(),
479 paint,
480 this->localToDevice(),
481 fSurfaceDrawContext->surfaceProps(),
482 &grPaint)) {
483 SkPath path;
484 path.setIsVolatile(true);
485 path.moveTo(pts[0]);
486 path.lineTo(pts[1]);
487 fSurfaceDrawContext->drawPath(this->clip(),
488 std::move(grPaint),
489 aa,
490 this->localToDevice(),
491 path,
493 }
494 return;
495 }
496 if (!paint.getMaskFilter() &&
497 paint.getStrokeWidth() > 0 && // drawStrokedLine doesn't support hairlines.
498 paint.getStrokeCap() != SkPaint::kRound_Cap) { // drawStrokedLine doesn't do round caps.
499 // Simple stroked line. Bypass path rendering.
500 GrPaint grPaint;
502 fSurfaceDrawContext->colorInfo(),
503 paint,
504 this->localToDevice(),
505 fSurfaceDrawContext->surfaceProps(),
506 &grPaint)) {
507 fSurfaceDrawContext->drawStrokedLine(this->clip(),
508 std::move(grPaint),
509 aa,
510 this->localToDevice(),
511 pts,
513 }
514 return;
515 }
516 }
517
518 const GrCaps* caps = fContext->priv().caps();
519 SkScalar scales[2];
520 bool isHairline =
521 ((0 == width) ||
522 (1 == width && this->localToDevice().getMinMaxScales(scales) &&
523 SkScalarNearlyEqual(scales[0], 1.f) && SkScalarNearlyEqual(scales[1], 1.f))) &&
524
525 // Don't do this as a hairline draw, which will emit line primitives, if
526 // lines are not permitted by caps.
528 caps->avoidLineDraws());
529
530 // we only handle non-coverage-aa hairlines and paints without path effects or mask filters,
531 // else we let the SkDraw call our drawPath()
532 if (!isHairline ||
533 paint.getPathEffect() ||
534 paint.getMaskFilter() ||
535 fSurfaceDrawContext->chooseAAType(aa) == GrAAType::kCoverage) {
536 SkRasterClip rc(this->devClipBounds());
538 // don't need to set fBlitterChoose, as it should never get used
539 draw.fDst = SkPixmap(SkImageInfo::MakeUnknown(this->width(), this->height()), nullptr, 0);
540 draw.fCTM = &this->localToDevice();
541 draw.fRC = &rc;
542 draw.drawDevicePoints(mode, count, pts, paint, this);
543 return;
544 }
545
546 GrPaint grPaint;
548 fSurfaceDrawContext->colorInfo(),
549 paint,
550 this->localToDevice(),
551 fSurfaceDrawContext->surfaceProps(),
552 &grPaint)) {
553 return;
554 }
555
556 static constexpr SkVertices::VertexMode kIgnoredMode = SkVertices::kTriangles_VertexMode;
557 sk_sp<SkVertices> vertices = SkVertices::MakeCopy(kIgnoredMode, SkToS32(count), pts, nullptr,
558 nullptr);
559
560 GrPrimitiveType primitiveType = point_mode_to_primitive_type(mode);
561 fSurfaceDrawContext->drawVertices(this->clip(), std::move(grPaint), this->localToDevice(),
562 std::move(vertices), &primitiveType);
563}
564
565///////////////////////////////////////////////////////////////////////////////
566
567void Device::drawRect(const SkRect& rect, const SkPaint& paint) {
569 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawRect", fContext.get());
570
571 GrStyle style(paint);
572
573 // A couple reasons we might need to call drawPath.
574 if (paint.getMaskFilter() || paint.getPathEffect()) {
575 GrStyledShape shape(rect, style);
576
577 GrBlurUtils::DrawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(),
578 this->clip(), paint, this->localToDevice(), shape);
579 return;
580 }
581
582 GrPaint grPaint;
584 fSurfaceDrawContext->colorInfo(),
585 paint,
586 this->localToDevice(),
587 fSurfaceDrawContext->surfaceProps(),
588 &grPaint)) {
589 return;
590 }
591
592 fSurfaceDrawContext->drawRect(this->clip(), std::move(grPaint),
593 fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), rect,
594 &style);
595}
596
598 const SkPoint clip[4],
599 SkCanvas::QuadAAFlags aaFlags,
600 const SkColor4f& color,
601 SkBlendMode mode) {
603 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawEdgeAAQuad", fContext.get());
604
605 SkPMColor4f dstColor = SkColor4fPrepForDst(color, fSurfaceDrawContext->colorInfo()).premul();
606
607 GrPaint grPaint;
608 grPaint.setColor4f(dstColor);
609 if (mode != SkBlendMode::kSrcOver) {
611 }
612
613 if (clip) {
614 // Use fillQuadWithEdgeAA
615 fSurfaceDrawContext->fillQuadWithEdgeAA(this->clip(),
616 std::move(grPaint),
617 SkToGrQuadAAFlags(aaFlags),
618 this->localToDevice(),
619 clip,
620 nullptr);
621 } else {
622 // Use fillRectWithEdgeAA to preserve mathematical properties of dst being rectangular
623 fSurfaceDrawContext->fillRectWithEdgeAA(this->clip(),
624 std::move(grPaint),
625 SkToGrQuadAAFlags(aaFlags),
626 this->localToDevice(),
627 rect);
628 }
629}
630
631///////////////////////////////////////////////////////////////////////////////
632
633void Device::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
635 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawRRect", fContext.get());
636
637 auto mf = paint.getMaskFilter();
638 if (mf) {
640 mf = nullptr; // already handled in SkPaintToGrPaint
641 }
642 }
643
644 GrStyle style(paint);
645
646 if (mf || style.pathEffect()) {
647 // A path effect will presumably transform this rrect into something else.
648 GrStyledShape shape(rrect, style);
649
650 GrBlurUtils::DrawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(),
651 this->clip(), paint, this->localToDevice(), shape);
652 return;
653 }
654
655 SkASSERT(!style.pathEffect());
656
657 GrPaint grPaint;
659 fSurfaceDrawContext->colorInfo(),
660 paint,
661 this->localToDevice(),
662 fSurfaceDrawContext->surfaceProps(),
663 &grPaint)) {
664 return;
665 }
666
667 fSurfaceDrawContext->drawRRect(this->clip(), std::move(grPaint),
668 fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
669 rrect, style);
670}
671
672void Device::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
674 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawDRRect", fContext.get());
675 if (outer.isEmpty()) {
676 return;
677 }
678
679 if (inner.isEmpty()) {
680 return this->drawRRect(outer, paint);
681 }
682
683 SkStrokeRec stroke(paint);
684
685 if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) {
686 // For axis-aligned filled DRRects, just draw a regular rrect with inner clipped out using a
687 // coverage FP instead of using path rendering.
688 if (auto fp = make_inverse_rrect_fp(this->localToDevice(), inner,
689 fSurfaceDrawContext->chooseAA(paint),
690 *fSurfaceDrawContext->caps()->shaderCaps())) {
691 GrPaint grPaint;
693 fSurfaceDrawContext->colorInfo(),
694 paint,
695 this->localToDevice(),
696 fSurfaceDrawContext->surfaceProps(),
697 &grPaint)) {
698 return;
699 }
701 grPaint.setCoverageFragmentProcessor(std::move(fp));
702 fSurfaceDrawContext->drawRRect(this->clip(), std::move(grPaint),
703 fSurfaceDrawContext->chooseAA(paint),
704 this->localToDevice(), outer, GrStyle());
705 return;
706 }
707 }
708
709 SkPath path;
710 path.setIsVolatile(true);
711 path.addRRect(outer);
712 path.addRRect(inner);
713 path.setFillType(SkPathFillType::kEvenOdd);
714
715 // TODO: We are losing the possible mutability of the path here but this should probably be
716 // fixed by upgrading GrStyledShape to handle DRRects.
717 GrStyledShape shape(path, paint);
718
719 GrBlurUtils::DrawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), this->clip(),
720 paint, this->localToDevice(), shape);
721}
722
723/////////////////////////////////////////////////////////////////////////////
724
725void Device::drawRegion(const SkRegion& region, const SkPaint& paint) {
727
728 if (paint.getMaskFilter()) {
729 SkPath path;
730 region.getBoundaryPath(&path);
731 path.setIsVolatile(true);
732 return this->drawPath(path, paint, true);
733 }
734
735 GrPaint grPaint;
737 fSurfaceDrawContext->colorInfo(),
738 paint,
739 this->localToDevice(),
740 fSurfaceDrawContext->surfaceProps(),
741 &grPaint)) {
742 return;
743 }
744
745 fSurfaceDrawContext->drawRegion(this->clip(), std::move(grPaint),
746 fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
747 region, GrStyle(paint));
748}
749
750void Device::drawOval(const SkRect& oval, const SkPaint& paint) {
752 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawOval", fContext.get());
753
754 if (paint.getMaskFilter()) {
755 // The RRect path can handle special case blurring
756 SkRRect rr = SkRRect::MakeOval(oval);
757 return this->drawRRect(rr, paint);
758 }
759
760 GrPaint grPaint;
762 fSurfaceDrawContext->colorInfo(),
763 paint,
764 this->localToDevice(),
765 fSurfaceDrawContext->surfaceProps(),
766 &grPaint)) {
767 return;
768 }
769
770 fSurfaceDrawContext->drawOval(this->clip(), std::move(grPaint),
771 fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), oval,
772 GrStyle(paint));
773}
774
775void Device::drawArc(const SkRect& oval,
776 SkScalar startAngle,
777 SkScalar sweepAngle,
778 bool useCenter,
779 const SkPaint& paint) {
781 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawArc", fContext.get());
782 if (paint.getMaskFilter()) {
783 this->SkDevice::drawArc(oval, startAngle, sweepAngle, useCenter, paint);
784 return;
785 }
786 GrPaint grPaint;
788 fSurfaceDrawContext->colorInfo(),
789 paint,
790 this->localToDevice(),
791 fSurfaceDrawContext->surfaceProps(),
792 &grPaint)) {
793 return;
794 }
795
796 fSurfaceDrawContext->drawArc(this->clip(), std::move(grPaint),
797 fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), oval,
798 startAngle, sweepAngle, useCenter, GrStyle(paint));
799}
800
801///////////////////////////////////////////////////////////////////////////////
802
803void Device::drawPath(const SkPath& origSrcPath, const SkPaint& paint, bool pathIsMutable) {
804#if defined(GR_TEST_UTILS)
805 if (fContext->priv().options().fAllPathsVolatile && !origSrcPath.isVolatile()) {
806 this->drawPath(SkPath(origSrcPath).setIsVolatile(true), paint, true);
807 return;
808 }
809#endif
811 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawPath", fContext.get());
812 if (!paint.getMaskFilter()) {
813 GrPaint grPaint;
815 fSurfaceDrawContext->colorInfo(),
816 paint,
817 this->localToDevice(),
818 fSurfaceDrawContext->surfaceProps(),
819 &grPaint)) {
820 return;
821 }
822 fSurfaceDrawContext->drawPath(this->clip(), std::move(grPaint),
823 fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
824 origSrcPath, GrStyle(paint));
825 return;
826 }
827
828 // TODO: losing possible mutability of 'origSrcPath' here
829 GrStyledShape shape(origSrcPath, paint);
830
831 GrBlurUtils::DrawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), this->clip(),
832 paint, this->localToDevice(), shape);
833}
834
836 SkColorType colorType) const {
838 fContext, fSurfaceDrawContext->origin(), surfaceProps, colorType);
839}
840
843
844 // TODO: this makes a tight copy of 'bitmap' but it doesn't have to be (given SkSpecialImage's
845 // semantics). Since this is cached we would have to bake the fit into the cache key though.
846 auto view = std::get<0>(
847 GrMakeCachedBitmapProxyView(fContext.get(), bitmap, /*label=*/"Device_MakeSpecial"));
848 if (!view) {
849 return nullptr;
850 }
851
852 const SkIRect rect = SkIRect::MakeSize(view.proxy()->dimensions());
853
854 // GrMakeCachedBitmapProxyView creates a tight copy of 'bitmap' so we don't have to subset
855 // the special image
856 return SkSpecialImages::MakeDeferredFromGpu(fContext.get(),
857 rect,
858 bitmap.getGenerationID(),
859 std::move(view),
860 {SkColorTypeToGrColorType(bitmap.colorType()),
861 kPremul_SkAlphaType,
862 bitmap.refColorSpace()},
863 this->surfaceProps());
864}
865
868
869 SkPixmap pm;
870 if (image->isTextureBacked()) {
871 auto [view, ct] =
872 skgpu::ganesh::AsView(this->recordingContext(), image, skgpu::Mipmapped::kNo);
873 SkASSERT(view);
874
875 return SkSpecialImages::MakeDeferredFromGpu(
876 fContext.get(),
878 image->uniqueID(),
879 std::move(view),
880 {ct, kPremul_SkAlphaType, image->refColorSpace()},
881 this->surfaceProps());
882 } else if (image->peekPixels(&pm)) {
883 SkBitmap bm;
884
885 bm.installPixels(pm);
886 return this->makeSpecial(bm);
887 } else {
888 return nullptr;
889 }
890}
891
892sk_sp<SkSpecialImage> Device::snapSpecial(const SkIRect& subset, bool forceCopy) {
894
895 auto sdc = fSurfaceDrawContext.get();
896
897 // If we are wrapping a vulkan secondary command buffer, then we can't snap off a special image
898 // since it would require us to make a copy of the underlying VkImage which we don't have access
899 // to. Additionaly we can't stop and start the render pass that is used with the secondary
900 // command buffer.
901 if (sdc->wrapsVkSecondaryCB()) {
902 return nullptr;
903 }
904
905 SkASSERT(sdc->asSurfaceProxy());
906
907 SkIRect finalSubset = subset;
908 GrSurfaceProxyView view = sdc->readSurfaceView();
909 if (forceCopy || !view.asTextureProxy()) {
910 // When the device doesn't have a texture, or a copy is requested, we create a temporary
911 // texture that matches the device contents
912 view = GrSurfaceProxyView::Copy(fContext.get(),
913 std::move(view),
914 skgpu::Mipmapped::kNo, // Don't auto generate mips
915 subset,
918 /*label=*/"Device_SnapSpecial"); // Always budgeted
919 if (!view) {
920 return nullptr;
921 }
922 // Since this copied only the requested subset, the special image wrapping the proxy no
923 // longer needs the original subset.
924 finalSubset = SkIRect::MakeSize(view.dimensions());
925 }
926
927 return SkSpecialImages::MakeDeferredFromGpu(fContext.get(),
928 finalSubset,
930 std::move(view),
931 GrColorInfo(this->imageInfo().colorInfo()),
932 this->surfaceProps());
933}
934
937
938 auto sdc = fSurfaceDrawContext.get();
939
940 // If we are wrapping a vulkan secondary command buffer, then we can't snap off a special image
941 // since it would require us to make a copy of the underlying VkImage which we don't have access
942 // to. Additionaly we can't stop and start the render pass that is used with the secondary
943 // command buffer.
944 if (sdc->wrapsVkSecondaryCB()) {
945 return nullptr;
946 }
947
948 SkASSERT(sdc->asSurfaceProxy());
949
950 auto scaledContext = sdc->rescale(sdc->imageInfo().makeDimensions(dstDims),
951 sdc->origin(),
952 subset,
953 RescaleGamma::kSrc,
954 RescaleMode::kLinear);
955 if (!scaledContext) {
956 return nullptr;
957 }
958
959 return SkSpecialImages::MakeDeferredFromGpu(fContext.get(),
960 SkIRect::MakeSize(dstDims),
962 scaledContext->readSurfaceView(),
963 GrColorInfo(this->imageInfo().colorInfo()),
964 this->surfaceProps());
965}
966
968 const SkSamplingOptions& sampling,
969 const SkPaint& paint) {
971 // clear of the source device must occur before CHECK_SHOULD_DRAW
972 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawDevice", fContext.get());
973 this->SkDevice::drawDevice(device, sampling, paint);
974}
975
977 const SkRect* src,
978 const SkRect& dst,
979 const SkSamplingOptions& sampling,
980 const SkPaint& paint,
981 SkCanvas::SrcRectConstraint constraint) {
983
984 GrAA aa = fSurfaceDrawContext->chooseAA(paint);
987
988 this->drawImageQuadDirect(image,
989 src ? *src
991 dst,
992 /* dstClip= */ nullptr,
993 aaFlags,
994 /* preViewMatrix= */ nullptr,
995 sampling,
996 paint,
997 constraint);
998}
999
1001 const SkImage* image,
1002 const SkRect* src,
1003 const SkRect& dst,
1004 const SkSamplingOptions& sampling,
1005 const SkPaint& paint,
1006 SkCanvas::SrcRectConstraint constraint) {
1007 GrRecordingContext* rCtx = canvas->recordingContext();
1008 if (!rCtx) {
1009 return false;
1010 }
1012
1013 GrAA aa = fSurfaceDrawContext->chooseAA(paint);
1016
1017 // NOTE: if the context is not a direct context, it doesn't have access to the resource
1018 // cache, and theoretically, the resource cache's limits could be being changed on
1019 // another thread, so even having access to just the limit wouldn't be a reliable
1020 // test during recording here.
1021 size_t cacheSize = 0;
1022 if (auto dCtx = GrAsDirectContext(rCtx)) {
1023 cacheSize = dCtx->getResourceCacheLimit();
1024 }
1025 size_t maxTextureSize = rCtx->maxTextureSize();
1026#if defined(GR_TEST_UTILS)
1027 if (gOverrideMaxTextureSizeGanesh) {
1028 maxTextureSize = gOverrideMaxTextureSizeGanesh;
1029 }
1030 gNumTilesDrawnGanesh.store(0, std::memory_order_relaxed);
1031#endif
1032
1033 [[maybe_unused]] auto [wasTiled, numTiles] = TiledTextureUtils::DrawAsTiledImageRect(
1034 canvas,
1035 image,
1036 src ? *src : SkRect::MakeIWH(image->width(), image->height()),
1037 dst,
1038 aaFlags,
1039 sampling,
1040 &paint,
1041 constraint,
1042 cacheSize,
1043 maxTextureSize);
1044#if defined(GR_TEST_UTILS)
1045 gNumTilesDrawnGanesh.store(numTiles, std::memory_order_relaxed);
1046#endif
1047 return wasTiled;
1048}
1049
1050void Device::drawViewLattice(GrSurfaceProxyView view,
1051 const GrColorInfo& info,
1052 std::unique_ptr<SkLatticeIter> iter,
1053 const SkRect& dst,
1054 SkFilterMode filter,
1055 const SkPaint& origPaint) {
1056 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawViewLattice", fContext.get());
1057 SkASSERT(view);
1058
1060
1061 if (!info.isAlphaOnly() && (paint->getColor() & 0x00FFFFFF) != 0x00FFFFFF) {
1062 paint.writable()->setColor(SkColorSetARGB(origPaint.getAlpha(), 0xFF, 0xFF, 0xFF));
1063 }
1064 GrPaint grPaint;
1065 // Passing null as shaderFP indicates that the GP will provide the shader.
1067 fSurfaceDrawContext->colorInfo(),
1068 *paint,
1069 this->localToDevice(),
1070 /*shaderFP=*/nullptr,
1071 fSurfaceDrawContext->surfaceProps(),
1072 &grPaint)) {
1073 return;
1074 }
1075
1076 if (info.isAlphaOnly()) {
1077 // If we were doing this with an FP graph we'd use a kDstIn blend between the texture
1078 // and the paint color.
1079 view.concatSwizzle(skgpu::Swizzle("aaaa"));
1080 }
1081 auto csxf = GrColorSpaceXform::Make(info, fSurfaceDrawContext->colorInfo());
1082
1083 fSurfaceDrawContext->drawImageLattice(this->clip(),
1084 std::move(grPaint),
1085 this->localToDevice(),
1086 std::move(view),
1087 info.alphaType(),
1088 std::move(csxf),
1089 filter,
1090 std::move(iter),
1091 dst);
1092}
1093
1095 const SkCanvas::Lattice& lattice,
1096 const SkRect& dst,
1097 SkFilterMode filter,
1098 const SkPaint& paint) {
1100 auto iter = std::make_unique<SkLatticeIter>(lattice, dst);
1101
1102 auto [view, ct] = skgpu::ganesh::AsView(this->recordingContext(), image, skgpu::Mipmapped::kNo);
1103 if (view) {
1104 GrColorInfo colorInfo(ct, image->alphaType(), image->refColorSpace());
1105 this->drawViewLattice(
1106 std::move(view), std::move(colorInfo), std::move(iter), dst, filter, paint);
1107 }
1108}
1109
1111 sk_sp<SkBlender> blender,
1112 const SkPaint& paint,
1113 bool skipColorXform) {
1115 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawVertices", fContext.get());
1116 SkASSERT(vertices);
1117
1118#ifdef SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER
1119 if (!paint.getShader()) {
1121 }
1122#endif
1123
1124 SkVerticesPriv info(vertices->priv());
1125
1126 GrPaint grPaint;
1127 if (!init_vertices_paint(fContext.get(),
1128 fSurfaceDrawContext->colorInfo(),
1129 paint,
1130 this->localToDevice(),
1131 blender.get(),
1132 info.hasColors(),
1133 fSurfaceDrawContext->surfaceProps(),
1134 &grPaint)) {
1135 return;
1136 }
1137 fSurfaceDrawContext->drawVertices(this->clip(),
1138 std::move(grPaint),
1139 this->localToDevice(),
1140 sk_ref_sp(const_cast<SkVertices*>(vertices)),
1141 nullptr,
1142 skipColorXform);
1143}
1144
1145void Device::drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
1147 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawMesh", fContext.get());
1148 if (!mesh.isValid()) {
1149 return;
1150 }
1151
1152 GrPaint grPaint;
1153 if (!init_vertices_paint(fContext.get(),
1154 fSurfaceDrawContext->colorInfo(),
1155 paint,
1156 this->localToDevice(),
1157 blender.get(),
1159 fSurfaceDrawContext->surfaceProps(),
1160 &grPaint)) {
1161 return;
1162 }
1163
1165 if (!init_mesh_child_effects(fContext.get(),
1166 fSurfaceDrawContext->colorInfo(),
1167 fSurfaceDrawContext->surfaceProps(),
1168 mesh,
1169 &meshChildFPs)) {
1170 return;
1171 }
1172 fSurfaceDrawContext->drawMesh(this->clip(), std::move(grPaint), this->localToDevice(), mesh,
1173 std::move(meshChildFPs));
1174}
1175
1176///////////////////////////////////////////////////////////////////////////////
1177
1178#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
1179void Device::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
1180#if defined(GR_TEST_UTILS)
1181 if (fContext->priv().options().fAllPathsVolatile && !path.isVolatile()) {
1182 this->drawShadow(SkPath(path).setIsVolatile(true), rec);
1183 return;
1184 }
1185#endif
1187 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawShadow", fContext.get());
1188
1189 if (!fSurfaceDrawContext->drawFastShadow(this->clip(), this->localToDevice(), path, rec)) {
1190 // failed to find an accelerated case
1191 this->SkDevice::drawShadow(path, rec);
1192 }
1193}
1194#endif // SK_ENABLE_OPTIMIZE_SIZE
1195
1196///////////////////////////////////////////////////////////////////////////////
1197
1198void Device::drawAtlas(const SkRSXform xform[],
1199 const SkRect texRect[],
1200 const SkColor colors[],
1201 int count,
1202 sk_sp<SkBlender> blender,
1203 const SkPaint& paint) {
1205 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawAtlas", fContext.get());
1206
1207 GrPaint grPaint;
1208 if (colors) {
1210 fSurfaceDrawContext->colorInfo(),
1211 paint,
1212 this->localToDevice(),
1213 blender.get(),
1214 fSurfaceDrawContext->surfaceProps(),
1215 &grPaint)) {
1216 return;
1217 }
1218 } else {
1220 fSurfaceDrawContext->colorInfo(),
1221 paint,
1222 this->localToDevice(),
1223 fSurfaceDrawContext->surfaceProps(),
1224 &grPaint)) {
1225 return;
1226 }
1227 }
1228
1229 fSurfaceDrawContext->drawAtlas(this->clip(), std::move(grPaint), this->localToDevice(), count,
1230 xform, texRect, colors);
1231}
1232
1233///////////////////////////////////////////////////////////////////////////////
1234
1236 const sktext::GlyphRunList& glyphRunList,
1237 const SkPaint& paint) {
1239 GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::ganesh::Device", "drawGlyphRunList", fContext.get());
1240 SkASSERT(!glyphRunList.hasRSXForm());
1241
1242 if (glyphRunList.blob() == nullptr) {
1243 // If the glyphRunList does not have an associated text blob, then it was created by one of
1244 // the direct draw APIs (drawGlyphs, etc.). Use a Slug to draw the glyphs.
1245 auto slug = this->convertGlyphRunListToSlug(glyphRunList, paint);
1246 if (slug != nullptr) {
1247 this->drawSlug(canvas, slug.get(), paint);
1248 }
1249 } else {
1250 fSurfaceDrawContext->drawGlyphRunList(canvas,
1251 this->clip(),
1252 this->localToDevice(),
1253 glyphRunList,
1254 this->strikeDeviceInfo(),
1255 paint);
1256 }
1257}
1258
1259///////////////////////////////////////////////////////////////////////////////
1260
1261void Device::drawDrawable(SkCanvas* canvas, SkDrawable* drawable, const SkMatrix* matrix) {
1263
1264 GrBackendApi api = this->recordingContext()->backend();
1265 if (GrBackendApi::kVulkan == api) {
1266 const SkMatrix& ctm = this->localToDevice();
1267 const SkMatrix& combinedMatrix = matrix ? SkMatrix::Concat(ctm, *matrix) : ctm;
1268 std::unique_ptr<SkDrawable::GpuDrawHandler> gpuDraw =
1269 drawable->snapGpuDrawHandler(api, combinedMatrix, this->devClipBounds(),
1270 this->imageInfo());
1271 if (gpuDraw) {
1272 fSurfaceDrawContext->drawDrawable(
1273 std::move(gpuDraw), combinedMatrix.mapRect(drawable->getBounds()));
1274 return;
1275 }
1276 }
1277 this->SkDevice::drawDrawable(canvas, drawable, matrix);
1278}
1279
1280
1281///////////////////////////////////////////////////////////////////////////////
1282
1286
1290
1291bool Device::wait(int numSemaphores,
1292 const GrBackendSemaphore* waitSemaphores,
1293 bool deleteSemaphoresAfterWait) {
1295
1296 return fSurfaceDrawContext->waitOnSemaphores(numSemaphores, waitSemaphores,
1297 deleteSemaphoresAfterWait);
1298}
1299
1301 fSurfaceDrawContext->discard();
1302}
1303
1305 fSurfaceDrawContext->resolveMSAA();
1306}
1307
1310 GrColorType grColorType,
1311 sk_sp<SkColorSpace> colorSpace,
1312 GrSurfaceOrigin origin,
1313 const SkSurfaceProps& props) {
1314 auto sdc = SurfaceDrawContext::Make(fContext.get(), grColorType, std::move(newRTP),
1315 std::move(colorSpace), origin, props);
1316 if (!sdc) {
1317 return false;
1318 }
1319
1320 SkASSERT(sdc->dimensions() == fSurfaceDrawContext->dimensions());
1321 SkASSERT(sdc->numSamples() == fSurfaceDrawContext->numSamples());
1322 SkASSERT(sdc->asSurfaceProxy()->priv().isExact());
1324 if (fContext->abandoned()) {
1325 return false;
1326 }
1327
1328 SkASSERT(fSurfaceDrawContext->asTextureProxy());
1329 SkAssertResult(sdc->blitTexture(fSurfaceDrawContext->readSurfaceView(),
1330 SkIRect::MakeWH(this->width(), this->height()),
1331 SkIPoint::Make(0, 0)));
1332 }
1333
1334 fSurfaceDrawContext = std::move(sdc);
1335 return true;
1336}
1337
1340
1341 const SkImageInfo& ii = this->imageInfo();
1342 GrRenderTargetProxy* oldRTP = this->targetProxy();
1343 GrSurfaceProxyView oldView = this->readSurfaceView();
1344
1345 auto grColorType = SkColorTypeToGrColorType(ii.colorType());
1346 auto format = fContext->priv().caps()->getDefaultBackendFormat(grColorType, GrRenderable::kYes);
1347 if (!format.isValid()) {
1348 return false;
1349 }
1350
1351 GrProxyProvider* proxyProvider = fContext->priv().proxyProvider();
1352 // This entry point is used by SkSurface_Ganesh::onCopyOnWrite so it must create a
1353 // kExact-backed render target proxy
1354 sk_sp<GrTextureProxy> proxy =
1355 proxyProvider->createProxy(format,
1356 ii.dimensions(),
1357 GrRenderable::kYes,
1358 oldRTP->numSamples(),
1359 oldView.mipmapped(),
1361 oldRTP->isBudgeted(),
1362 GrProtected::kNo,
1363 /*label=*/"BaseDevice_ReplaceBackingProxy");
1364 if (!proxy) {
1365 return false;
1366 }
1367
1368 return this->replaceBackingProxy(mode, sk_ref_sp(proxy->asRenderTargetProxy()),
1369 grColorType, ii.refColorSpace(), oldView.origin(),
1370 this->surfaceProps());
1371}
1372
1374 const SkIRect& srcRect,
1375 RescaleGamma rescaleGamma,
1376 RescaleMode rescaleMode,
1378 ReadPixelsContext context) {
1379 auto* sdc = fSurfaceDrawContext.get();
1380 // Context TODO: Elevate direct context requirement to public API.
1381 auto dContext = sdc->recordingContext()->asDirectContext();
1382 if (!dContext) {
1383 return;
1384 }
1385 sdc->asyncRescaleAndReadPixels(dContext, info, srcRect, rescaleGamma, rescaleMode, callback,
1386 context);
1387}
1388
1390 bool readAlpha,
1391 sk_sp<SkColorSpace> dstColorSpace,
1392 const SkIRect& srcRect,
1393 SkISize dstSize,
1394 RescaleGamma rescaleGamma,
1395 RescaleMode rescaleMode,
1397 ReadPixelsContext context) {
1398 auto* sdc = fSurfaceDrawContext.get();
1399 // Context TODO: Elevate direct context requirement to public API.
1400 auto dContext = sdc->recordingContext()->asDirectContext();
1401 if (!dContext) {
1402 return;
1403 }
1404 sdc->asyncRescaleAndReadPixelsYUV420(dContext,
1405 yuvColorSpace,
1406 readAlpha,
1407 std::move(dstColorSpace),
1408 srcRect,
1409 dstSize,
1410 rescaleGamma,
1411 rescaleMode,
1412 callback,
1413 context);
1414}
1415
1416///////////////////////////////////////////////////////////////////////////////
1417
1420
1421 SkSurfaceProps props =
1423
1425
1427 fContext.get(),
1429 cinfo.fInfo.refColorSpace(),
1431 cinfo.fInfo.dimensions(),
1432 props,
1433 fSurfaceDrawContext->numSamples(),
1434 skgpu::Mipmapped::kNo,
1435 fSurfaceDrawContext->asSurfaceProxy()->isProtected(),
1436 fSurfaceDrawContext->origin(),
1438 if (!sdc) {
1439 return nullptr;
1440 }
1441
1442 // Skia's convention is to only clear a device if it is non-opaque.
1444
1445 return Device::Make(std::move(sdc), cinfo.fInfo.alphaType(), init);
1446}
1447
1450 // TODO: Change the signature of newSurface to take a budgeted parameter.
1452 bool isProtected = this->targetProxy()->isProtected() == GrProtected::kYes;
1453 return SkSurfaces::RenderTarget(fContext.get(),
1454 kBudgeted,
1455 info,
1456 fSurfaceDrawContext->numSamples(),
1457 fSurfaceDrawContext->origin(),
1458 &props,
1459 /* shouldCreateWithMips= */ false,
1460 isProtected);
1461}
1462
1463////////////////////////////////////////////////////////////////////////////////////
1464
1467 this->android_utils_clipAsRgn(&clipRegion);
1468 if (clipRegion.isEmpty()) {
1469 return false;
1470 }
1471 auto sdc = fSurfaceDrawContext.get();
1472 SkASSERT(sdc);
1473 GrPaint grPaint;
1475 static constexpr GrUserStencilSettings kDrawToStencil(
1477 0x1,
1479 0x1,
1482 0x1>()
1483 );
1484 // Regions don't actually need AA, but in DMSAA mode everything is antialiased.
1485 GrAA aa = GrAA(fSurfaceDrawContext->alwaysAntialias());
1486 sdc->drawRegion(nullptr, std::move(grPaint), aa, SkMatrix::I(), clipRegion,
1487 GrStyle::SimpleFill(), &kDrawToStencil);
1488 return true;
1489}
1490
1492 return {this->surfaceProps(), this->scalerContextFlags(), &fSDFTControl};
1493}
1494
1503
1504void Device::drawSlug(SkCanvas* canvas, const sktext::gpu::Slug* slug, const SkPaint& paint) {
1505 SkASSERT(canvas);
1506 SkASSERT(slug);
1507 const sktext::gpu::SlugImpl* slugImpl = static_cast<const sktext::gpu::SlugImpl*>(slug);
1508#if defined(SK_DEBUG)
1509 if (!fContext->priv().options().fSupportBilerpFromGlyphAtlas) {
1510 // We can draw a slug if the atlas has padding or if the creation matrix and the
1511 // drawing matrix are the same. If they are the same, then the Slug will use the direct
1512 // drawing code and not use bi-lerp.
1513 SkMatrix slugMatrix = slugImpl->initialPositionMatrix();
1514 SkMatrix positionMatrix = this->localToDevice();
1515 positionMatrix.preTranslate(slugImpl->origin().x(), slugImpl->origin().y());
1516 SkASSERT(slugMatrix == positionMatrix);
1517 }
1518#endif
1519 auto atlasDelegate = [&](const sktext::gpu::AtlasSubRun* subRun,
1520 SkPoint drawOrigin,
1521 const SkPaint& paint,
1522 sk_sp<SkRefCnt> subRunStorage,
1524 auto[drawingClip, op] = subRun->makeAtlasTextOp(
1525 this->clip(), this->localToDevice(), drawOrigin, paint,
1526 std::move(subRunStorage), fSurfaceDrawContext.get());
1527 if (op != nullptr) {
1528 fSurfaceDrawContext->addDrawOp(drawingClip, std::move(op));
1529 }
1530 };
1531
1532 slugImpl->subRuns()->draw(canvas, slugImpl->origin(), paint, slugImpl, atlasDelegate);
1533}
1534
1535} // namespace skgpu::ganesh
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
int count
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
#define GR_CREATE_TRACE_MARKER_CONTEXT(classname, op, context)
Definition GrTracing.h:18
static GrQuadAAFlags SkToGrQuadAAFlags(unsigned flags)
GrPrimitiveType
Definition GrTypesPriv.h:42
GrClipEdgeType
static constexpr SkColorType GrColorTypeToSkColorType(GrColorType ct)
GrAA
GrColorType
static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct)
GrSurfaceOrigin
Definition GrTypes.h:147
GrBackendApi
Definition GrTypes.h:95
SkColor4f color
SkAlphaType
Definition SkAlphaType.h:26
@ kOpaque_SkAlphaType
pixel is opaque
Definition SkAlphaType.h:28
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkAssertResult(cond)
Definition SkAssert.h:123
#define SK_ABORT(message,...)
Definition SkAssert.h:70
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBackingFit
SkBlendMode
Definition SkBlendMode.h:38
@ kSrcOver
r = s + (1-sa)*d
SkClipOp
Definition SkClipOp.h:13
constexpr SkPMColor4f SK_PMColor4fTRANSPARENT
SkColorType
Definition SkColorType.h:19
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
Definition SkColorType.h:27
uint32_t SkColor
Definition SkColor.h:37
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition SkColor.h:49
bool SkPaintToGrPaintReplaceShader(GrRecordingContext *context, const GrColorInfo &dstColorInfo, const SkPaint &skPaint, const SkMatrix &ctm, std::unique_ptr< GrFragmentProcessor > shaderFP, const SkSurfaceProps &surfaceProps, GrPaint *grPaint)
Definition SkGr.cpp:570
SkColor4f SkColor4fPrepForDst(SkColor4f color, const GrColorInfo &colorInfo)
Definition SkGr.cpp:283
bool SkPaintToGrPaintWithBlend(GrRecordingContext *context, const GrColorInfo &dstColorInfo, const SkPaint &skPaint, const SkMatrix &ctm, SkBlender *primColorBlender, const SkSurfaceProps &surfaceProps, GrPaint *grPaint)
Definition SkGr.cpp:589
bool SkPaintToGrPaint(GrRecordingContext *context, const GrColorInfo &dstColorInfo, const SkPaint &skPaint, const SkMatrix &ctm, const SkSurfaceProps &surfaceProps, GrPaint *grPaint)
Definition SkGr.cpp:553
std::tuple< GrSurfaceProxyView, GrColorType > GrMakeCachedBitmapProxyView(GrRecordingContext *rContext, const SkBitmap &bitmap, std::string_view label, skgpu::Mipmapped mipmapped)
Definition SkGr.cpp:188
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static bool SkImageInfoValidConversion(const SkImageInfo &dst, const SkImageInfo &src)
SkYUVColorSpace
Definition SkImageInfo.h:68
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
const Context & fContext
SkFilterMode
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:107
@ kNeedNewImageUniqueID_SpecialImage
constexpr int32_t SkToS32(S x)
Definition SkTo.h:25
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition aaclip.cpp:27
const GrContextOptions & options() const
const GrCaps * caps() const
bool avoidLineDraws() const
Definition GrCaps.h:555
GrBackendFormat getDefaultBackendFormat(GrColorType, GrRenderable) const
Definition GrCaps.cpp:400
GrColorType colorType() const
Definition GrColorInfo.h:43
static sk_sp< GrColorSpaceXform > Make(SkColorSpace *src, SkAlphaType srcAT, SkColorSpace *dst, SkAlphaType dstAT)
virtual GrDirectContext * asDirectContext()
SK_API GrBackendApi backend() const
static const GrDisableColorXPFactory * Get()
void setXPFactory(const GrXPFactory *xpFactory)
Definition GrPaint.h:53
int hasCoverageFragmentProcessor() const
Definition GrPaint.h:83
void setColor4f(const SkPMColor4f &color)
Definition GrPaint.h:50
void setCoverageFragmentProcessor(std::unique_ptr< GrFragmentProcessor > fp)
Definition GrPaint.h:75
sk_sp< GrTextureProxy > createProxy(const GrBackendFormat &, SkISize dimensions, GrRenderable, int renderTargetSampleCnt, skgpu::Mipmapped, SkBackingFit, skgpu::Budgeted, GrProtected, std::string_view label, GrInternalSurfaceFlags=GrInternalSurfaceFlags::kNone, UseAllocator useAllocator=UseAllocator::kYes)
GrProxyProvider * proxyProvider()
GrRecordingContextPriv priv()
bool abandoned() override
SK_API bool colorTypeSupportedAsSurface(SkColorType colorType) const
SK_API int maxTextureSize() const
SkPathEffect * pathEffect() const
Definition GrStyle.h:119
static const GrStyle & SimpleFill()
Definition GrStyle.h:30
skgpu::Mipmapped mipmapped() const
void concatSwizzle(skgpu::Swizzle swizzle)
GrTextureProxy * asTextureProxy() const
SkISize dimensions() const
GrSurfaceOrigin origin() const
GrRenderTargetProxy * asRenderTargetProxy() const
static GrSurfaceProxyView Copy(GrRecordingContext *context, GrSurfaceProxyView src, skgpu::Mipmapped mipmapped, SkIRect srcRect, SkBackingFit fit, skgpu::Budgeted budgeted, std::string_view label)
GrProtected isProtected() const
skgpu::Budgeted isBudgeted() const
static const GrXPFactory * FromBlendMode(SkBlendMode)
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
Definition SkBitmap.cpp:323
static sk_sp< SkBlender > Mode(SkBlendMode mode)
virtual GrRecordingContext * recordingContext() const
SrcRectConstraint
Definition SkCanvas.h:1541
@ kLines_PointMode
draw each pair of points as a line segment
Definition SkCanvas.h:1242
@ kPolygon_PointMode
draw the array of points as a open polygon
Definition SkCanvas.h:1243
@ kPoints_PointMode
draw each point separately
Definition SkCanvas.h:1241
@ kNone_QuadAAFlags
Definition SkCanvas.h:1664
@ kAll_QuadAAFlags
Definition SkCanvas.h:1665
const SkImageInfo & imageInfo() const
Definition SkDevice.h:117
SkScalerContextFlags scalerContextFlags() const
Definition SkDevice.cpp:503
int height() const
Definition SkDevice.h:120
virtual void drawShadow(const SkPath &, const SkDrawShadowRec &)
const SkM44 & globalToDevice() const
Definition SkDevice.h:191
sk_sp< SkSpecialImage > snapSpecial()
Definition SkDevice.cpp:321
const SkMatrix & localToDevice() const
Definition SkDevice.h:179
virtual void drawDevice(SkDevice *, const SkSamplingOptions &, const SkPaint &)
Definition SkDevice.cpp:330
const SkSurfaceProps & surfaceProps() const
Definition SkDevice.h:131
virtual void drawDrawable(SkCanvas *, SkDrawable *, const SkMatrix *)
Definition SkDevice.cpp:299
int width() const
Definition SkDevice.h:119
SkIRect bounds() const
Definition SkDevice.h:125
virtual void drawArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint)
Definition SkDevice.cpp:133
const SkRasterClip * fRC
Definition SkDrawBase.h:154
SkPixmap fDst
Definition SkDrawBase.h:151
const SkMatrix * fCTM
Definition SkDrawBase.h:153
SkRect getBounds()
std::unique_ptr< GpuDrawHandler > snapGpuDrawHandler(GrBackendApi backendApi, const SkMatrix &matrix, const SkIRect &clipBounds, const SkImageInfo &bufferInfo)
Definition SkDrawable.h:89
uint32_t uniqueID() const
Definition SkImage.h:311
SkAlphaType alphaType() const
Definition SkImage.cpp:154
RescaleMode
Definition SkImage.h:587
bool peekPixels(SkPixmap *pixmap) const
Definition SkImage.cpp:34
int width() const
Definition SkImage.h:285
RescaleGamma
Definition SkImage.h:585
virtual bool isTextureBacked() const =0
int height() const
Definition SkImage.h:291
sk_sp< SkColorSpace > refColorSpace() const
Definition SkImage.cpp:158
bool getMinMaxScales(SkScalar scaleFactors[2]) const
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition SkMatrix.h:1775
static const SkMatrix & I()
SkMatrix & preTranslate(SkScalar dx, SkScalar dy)
Definition SkMatrix.cpp:263
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
bool isIdentity() const
Definition SkMatrix.h:223
bool isValid() const
Definition SkMesh.cpp:753
SkMeshSpecification * spec() const
Definition SkMesh.h:348
@ kRound_Cap
adds circle
Definition SkPaint.h:335
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
uint8_t getAlpha() const
Definition SkPaint.h:264
bool isVolatile() const
Definition SkPath.h:350
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition SkPath.cpp:1647
const SkImageInfo & info() const
Definition SkPixmap.h:135
static SkRRect MakeOval(const SkRect &oval)
Definition SkRRect.h:162
bool transform(const SkMatrix &matrix, SkRRect *dst) const
Definition SkRRect.cpp:436
bool isEmpty() const
Definition SkRRect.h:83
bool getBoundaryPath(SkPath *path) const
bool isRect() const
Definition SkRegion.h:152
const SkIRect & getBounds() const
Definition SkRegion.h:165
bool op(const SkIRect &rect, Op op)
Definition SkRegion.h:384
bool setRect(const SkIRect &rect)
Definition SkRegion.cpp:192
bool isEmpty() const
Definition SkRegion.h:146
bool setPath(const SkPath &path, const SkRegion &clip)
static SkStrikeCache * GlobalStrikeCache()
bool isFillStyle() const
Definition SkStrokeRec.h:51
SkSurfaceProps cloneWithPixelGeometry(SkPixelGeometry newPixelGeometry) const
@ kRetain_ContentChangeMode
preserves surface on change
Definition SkSurface.h:205
static sk_sp< SkVertices > MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[])
@ kTriangles_VertexMode
Definition SkVertices.h:31
SkVerticesPriv priv()
T * get() const
Definition SkRefCnt.h:303
static std::tuple< bool, size_t > DrawAsTiledImageRect(SkCanvas *, const SkImage *, const SkRect &srcRect, const SkRect &dstRect, SkCanvas::QuadAAFlags, const SkSamplingOptions &, const SkPaint *, SkCanvas::SrcRectConstraint, size_t cacheSize, size_t maxTextureSize)
void clipPath(const SkMatrix &ctm, const SkPath &path, GrAA aa, SkClipOp op)
Definition ClipStack.h:80
void clipRect(const SkMatrix &ctm, const SkRect &rect, GrAA aa, SkClipOp op)
Definition ClipStack.h:74
SkIRect getConservativeBounds() const override
void drawArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint) override
Definition Device.cpp:775
void drawShadow(const SkPath &, const SkDrawShadowRec &) override
Definition Device.cpp:1179
void drawOval(const SkRect &oval, const SkPaint &paint) override
Definition Device.cpp:750
void android_utils_clipAsRgn(SkRegion *) const override
Definition Device.cpp:411
void drawDRRect(const SkRRect &outer, const SkRRect &inner, const SkPaint &paint) override
Definition Device.cpp:672
void drawPath(const SkPath &path, const SkPaint &paint, bool pathIsMutable) override
Definition Device.cpp:803
SkImage::ReadPixelsContext ReadPixelsContext
Definition Device.h:121
void drawPaint(const SkPaint &paint) override
Definition Device.cpp:443
SkStrikeDeviceInfo strikeDeviceInfo() const override
Definition Device.cpp:1491
GrSurfaceProxyView readSurfaceView()
Definition Device.cpp:1283
void drawRect(const SkRect &r, const SkPaint &paint) override
Definition Device.cpp:567
void drawVertices(const SkVertices *, sk_sp< SkBlender >, const SkPaint &, bool) override
Definition Device.cpp:1110
void drawEdgeAAQuad(const SkRect &rect, const SkPoint clip[4], SkCanvas::QuadAAFlags aaFlags, const SkColor4f &color, SkBlendMode mode) override
Definition Device.cpp:597
bool android_utils_clipWithStencil() override
Definition Device.cpp:1465
void drawDrawable(SkCanvas *, SkDrawable *, const SkMatrix *) override
Definition Device.cpp:1261
sk_sp< sktext::gpu::Slug > convertGlyphRunListToSlug(const sktext::GlyphRunList &glyphRunList, const SkPaint &paint) override
Definition Device.cpp:1495
bool drawAsTiledImageRect(SkCanvas *, const SkImage *, const SkRect *src, const SkRect &dst, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint) override
Definition Device.cpp:1000
bool isClipAntiAliased() const override
Definition Device.cpp:431
void drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint[], const SkPaint &paint) override
Definition Device.cpp:460
bool onWritePixels(const SkPixmap &, int, int) override
Definition Device.cpp:341
bool onReadPixels(const SkPixmap &, int, int) override
Definition Device.cpp:329
sk_sp< SkSpecialImage > snapSpecialScaled(const SkIRect &subset, const SkISize &dstDims) override
Definition Device.cpp:935
sk_sp< SkSurface > makeSurface(const SkImageInfo &, const SkSurfaceProps &) override
Definition Device.cpp:1448
GrRenderTargetProxy * targetProxy()
Definition Device.cpp:1287
bool wait(int numSemaphores, const GrBackendSemaphore *waitSemaphores, bool deleteSemaphoresAfterWait)
Definition Device.cpp:1291
void drawAtlas(const SkRSXform[], const SkRect[], const SkColor[], int count, sk_sp< SkBlender >, const SkPaint &) override
Definition Device.cpp:1198
SurfaceFillContext * surfaceFillContext()
Definition Device.cpp:368
void drawMesh(const SkMesh &, sk_sp< SkBlender >, const SkPaint &) override
Definition Device.cpp:1145
void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, bool readAlpha, sk_sp< SkColorSpace > dstColorSpace, const SkIRect &srcRect, SkISize dstSize, RescaleGamma rescaleGamma, RescaleMode, ReadPixelsCallback callback, ReadPixelsContext context)
Definition Device.cpp:1389
sk_sp< skif::Backend > createImageFilteringBackend(const SkSurfaceProps &surfaceProps, SkColorType colorType) const override
Definition Device.cpp:835
void asyncRescaleAndReadPixels(const SkImageInfo &info, const SkIRect &srcRect, RescaleGamma rescaleGamma, RescaleMode rescaleMode, ReadPixelsCallback callback, ReadPixelsContext context)
Definition Device.cpp:1373
SkImage::ReadPixelsCallback ReadPixelsCallback
Definition Device.h:120
bool onAccessPixels(SkPixmap *) override
Definition Device.cpp:353
void drawImageRect(const SkImage *, const SkRect *src, const SkRect &dst, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint) override
Definition Device.cpp:976
void drawDevice(SkDevice *, const SkSamplingOptions &, const SkPaint &) override
Definition Device.cpp:967
void clipRegion(const SkRegion &globalRgn, SkClipOp op) override
Definition Device.cpp:394
SkIRect devClipBounds() const override
Definition Device.h:261
void drawRRect(const SkRRect &r, const SkPaint &paint) override
Definition Device.cpp:633
SurfaceDrawContext * surfaceDrawContext()
Definition Device.cpp:358
bool replaceBackingProxy(SkSurface::ContentChangeMode, sk_sp< GrRenderTargetProxy >, GrColorType, sk_sp< SkColorSpace >, GrSurfaceOrigin, const SkSurfaceProps &)
Definition Device.cpp:1308
void clipPath(const SkPath &path, SkClipOp op, bool aa) override
Definition Device.cpp:383
static sk_sp< Device > Make(GrRecordingContext *, GrColorType, sk_sp< GrSurfaceProxy >, sk_sp< SkColorSpace >, GrSurfaceOrigin, const SkSurfaceProps &, InitContents)
Definition Device.cpp:212
void onDrawGlyphRunList(SkCanvas *, const sktext::GlyphRunList &, const SkPaint &paint) override
Definition Device.cpp:1235
GrRecordingContext * recordingContext() const override
Definition Device.h:101
void drawRegion(const SkRegion &r, const SkPaint &paint) override
Definition Device.cpp:725
void drawSlug(SkCanvas *, const sktext::gpu::Slug *slug, const SkPaint &paint) override
Definition Device.cpp:1504
sk_sp< SkDevice > createDevice(const CreateInfo &, const SkPaint *) override
Definition Device.cpp:1418
void drawImageLattice(const SkImage *, const SkCanvas::Lattice &, const SkRect &dst, SkFilterMode, const SkPaint &) override
Definition Device.cpp:1094
sk_sp< SkSpecialImage > makeSpecial(const SkBitmap &) override
Definition Device.cpp:841
const GrColorInfo & colorInfo() const
GrSurfaceProxyView readSurfaceView()
static std::unique_ptr< SurfaceDrawContext > Make(GrRecordingContext *, GrColorType, sk_sp< GrSurfaceProxy >, sk_sp< SkColorSpace >, GrSurfaceOrigin, const SkSurfaceProps &)
static std::unique_ptr< SurfaceDrawContext > MakeWithFallback(GrRecordingContext *, GrColorType, sk_sp< SkColorSpace >, SkBackingFit, SkISize dimensions, const SkSurfaceProps &, int sampleCnt, skgpu::Mipmapped, skgpu::Protected, GrSurfaceOrigin=kBottomLeft_GrSurfaceOrigin, skgpu::Budgeted=skgpu::Budgeted::kYes)
const SkTextBlob * blob() const
Definition GlyphRun.h:117
bool hasRSXForm() const
Definition GlyphRun.h:105
const gpu::SubRunContainerOwner & subRuns() const
Definition SlugImpl.h:57
const SkMatrix & initialPositionMatrix() const
Definition SlugImpl.h:54
SkPoint origin() const
Definition SlugImpl.h:55
static sk_sp< SlugImpl > Make(const SkMatrix &viewMatrix, const sktext::GlyphRunList &glyphRunList, const SkPaint &paint, SkStrikeDeviceInfo strikeDeviceInfo, sktext::StrikeForGPUCacheInterface *strikeCache)
Definition SlugImpl.cpp:74
const Paint & paint
VkDevice device
Definition main.cc:53
sk_sp< SkImage > image
Definition examples.cpp:29
float SkScalar
Definition extension.cpp:12
FlutterSemanticsFlag flags
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlPixelBufferTexturePrivate * priv
uint32_t uint32_t * format
#define ASSERT_SINGLE_OWNER
Definition Device.cpp:120
double y
double x
void DrawShapeWithMaskFilter(GrRecordingContext *rContext, skgpu::ganesh::SurfaceDrawContext *sdc, const GrClip *clip, const GrStyledShape &shape, GrPaint &&paint, const SkMatrix &viewMatrix, const SkMaskFilter *mf)
GrFPResult MakeChildFP(const SkRuntimeEffect::ChildPtr &child, const GrFPArgs &childArgs)
bool IsSupported(const SkMaskFilter *maskfilter)
GrFPResult Make(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, const SkRRect &, const GrShaderCaps &)
SkRRect rrect
Definition SkRecords.h:232
SkMesh mesh
Definition SkRecords.h:345
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
const uint32_t fp
std::tuple< GrSurfaceProxyView, GrColorType > AsView(GrRecordingContext *rContext, const SkImage *img, skgpu::Mipmapped mipmapped, GrImageTexGenPolicy policy)
Budgeted
Definition GpuTypes.h:35
Mipmapped
Definition GpuTypes.h:53
Protected
Definition GpuTypes.h:61
sk_sp< Backend > MakeGaneshBackend(sk_sp< GrRecordingContext > context, GrSurfaceOrigin origin, const SkSurfaceProps &surfaceProps, SkColorType colorType)
Definition ref_ptr.h:256
static constexpr Init< Ref, Test, TestMask, PassOp, FailOp, WriteMask > StaticInit()
const SkPixelGeometry fPixelGeometry
Definition SkDevice.h:307
const SkImageInfo fInfo
Definition SkDevice.h:306
static constexpr SkIPoint Make(int32_t x, int32_t y)
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition SkRect.h:56
bool isOpaque() const
sk_sp< SkColorSpace > refColorSpace() const
SkISize dimensions() const
static SkImageInfo MakeUnknown()
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkAlphaType alphaType() const
SkColorType colorType() const
static bool HasColors(const SkMeshSpecification &spec)
Definition SkMeshPriv.h:30
constexpr float y() const
constexpr float x() const
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595
static SkRect MakeIWH(int w, int h)
Definition SkRect.h:623