• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
7 
8 #include "src/gpu/v1/Device_v1.h"
9 
10 #include "include/core/SkImageFilter.h"
11 #include "include/core/SkMaskFilter.h"
12 #include "include/core/SkPathEffect.h"
13 #include "include/core/SkPicture.h"
14 #include "include/core/SkSurface.h"
15 #include "include/core/SkVertices.h"
16 #include "include/effects/SkRuntimeEffect.h"
17 #include "include/gpu/GrDirectContext.h"
18 #include "include/gpu/GrRecordingContext.h"
19 #include "include/private/SkShadowFlags.h"
20 #include "include/private/SkTo.h"
21 #include "include/private/chromium/GrSlug.h"
22 #include "src/core/SkCanvasPriv.h"
23 #include "src/core/SkClipStack.h"
24 #include "src/core/SkCustomMeshPriv.h"
25 #include "src/core/SkDraw.h"
26 #include "src/core/SkImageFilterCache.h"
27 #include "src/core/SkImageFilter_Base.h"
28 #include "src/core/SkLatticeIter.h"
29 #include "src/core/SkPictureData.h"
30 #include "src/core/SkRRectPriv.h"
31 #include "src/core/SkRasterClip.h"
32 #include "src/core/SkRecord.h"
33 #include "src/core/SkStroke.h"
34 #include "src/core/SkTLazy.h"
35 #include "src/core/SkVerticesPriv.h"
36 #include "src/gpu/GrBlurUtils.h"
37 #include "src/gpu/GrDirectContextPriv.h"
38 #include "src/gpu/GrGpu.h"
39 #include "src/gpu/GrRecordingContextPriv.h"
40 #include "src/gpu/GrStyle.h"
41 #include "src/gpu/GrSurfaceProxyPriv.h"
42 #include "src/gpu/GrTracing.h"
43 #include "src/gpu/SkGr.h"
44 #include "src/gpu/effects/GrDisableColorXP.h"
45 #include "src/gpu/effects/GrRRectEffect.h"
46 #include "src/gpu/geometry/GrStyledShape.h"
47 #include "src/image/SkImage_Base.h"
48 #include "src/image/SkReadPixelsRec.h"
49 #include "src/image/SkSurface_Gpu.h"
50 #include "src/utils/SkUTF.h"
51 
52 #define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(fContext->priv().singleOwner())
53 
54 
55 ///////////////////////////////////////////////////////////////////////////////
56 
57 namespace {
58 
force_aa_clip(const skgpu::v1::SurfaceDrawContext * sdc)59 bool force_aa_clip(const skgpu::v1::SurfaceDrawContext* sdc) {
60     return sdc->numSamples() > 1 || sdc->alwaysAntialias();
61 }
62 
point_mode_to_primitive_type(SkCanvas::PointMode mode)63 inline GrPrimitiveType point_mode_to_primitive_type(SkCanvas::PointMode mode) {
64     switch (mode) {
65         case SkCanvas::kPoints_PointMode:
66             return GrPrimitiveType::kPoints;
67         case SkCanvas::kLines_PointMode:
68             return GrPrimitiveType::kLines;
69         case SkCanvas::kPolygon_PointMode:
70             return GrPrimitiveType::kLineStrip;
71     }
72     SK_ABORT("Unexpected mode");
73 }
74 
make_inverse_rrect_fp(const SkMatrix & viewMatrix,const SkRRect & rrect,GrAA aa,const GrShaderCaps & shaderCaps)75 std::unique_ptr<GrFragmentProcessor> make_inverse_rrect_fp(const SkMatrix& viewMatrix,
76                                                            const SkRRect& rrect, GrAA aa,
77                                                            const GrShaderCaps& shaderCaps) {
78     SkTCopyOnFirstWrite<SkRRect> devRRect(rrect);
79     if (viewMatrix.isIdentity() || rrect.transform(viewMatrix, devRRect.writable())) {
80         auto edgeType = (aa == GrAA::kYes) ? GrClipEdgeType::kInverseFillAA
81                                            : GrClipEdgeType::kInverseFillBW;
82         auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr, edgeType, *devRRect,
83                                                  shaderCaps);
84         return (success) ? std::move(fp) : nullptr;
85     }
86     return nullptr;
87 }
88 
init_vertices_paint(GrRecordingContext * rContext,const GrColorInfo & colorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,sk_sp<SkBlender> blender,bool hasColors,GrPaint * grPaint)89 bool init_vertices_paint(GrRecordingContext* rContext,
90                          const GrColorInfo& colorInfo,
91                          const SkPaint& skPaint,
92                          const SkMatrixProvider& matrixProvider,
93                          sk_sp<SkBlender> blender,
94                          bool hasColors,
95                          GrPaint* grPaint) {
96     if (hasColors) {
97         return SkPaintToGrPaintWithBlend(rContext,
98                                          colorInfo,
99                                          skPaint,
100                                          matrixProvider,
101                                          blender.get(),
102                                          grPaint);
103     } else {
104         return SkPaintToGrPaint(rContext, colorInfo, skPaint, matrixProvider, grPaint);
105     }
106 }
107 
108 } // anonymous namespace
109 
110 namespace skgpu::v1 {
111 
Make(GrRecordingContext * rContext,GrColorType colorType,sk_sp<GrSurfaceProxy> proxy,sk_sp<SkColorSpace> colorSpace,GrSurfaceOrigin origin,const SkSurfaceProps & surfaceProps,InitContents init)112 sk_sp<BaseDevice> Device::Make(GrRecordingContext* rContext,
113                                GrColorType colorType,
114                                sk_sp<GrSurfaceProxy> proxy,
115                                sk_sp<SkColorSpace> colorSpace,
116                                GrSurfaceOrigin origin,
117                                const SkSurfaceProps& surfaceProps,
118                                InitContents init) {
119     auto sdc = SurfaceDrawContext::Make(rContext,
120                                         colorType,
121                                         std::move(proxy),
122                                         std::move(colorSpace),
123                                         origin,
124                                         surfaceProps);
125 
126     return Device::Make(std::move(sdc), kPremul_SkAlphaType, init);
127 }
128 
Make(std::unique_ptr<SurfaceDrawContext> sdc,SkAlphaType alphaType,InitContents init)129 sk_sp<BaseDevice> Device::Make(std::unique_ptr<SurfaceDrawContext> sdc,
130                                SkAlphaType alphaType,
131                                InitContents init) {
132     if (!sdc) {
133         return nullptr;
134     }
135 
136     GrRecordingContext* rContext = sdc->recordingContext();
137     if (rContext->abandoned()) {
138         return nullptr;
139     }
140 
141     SkColorType ct = GrColorTypeToSkColorType(sdc->colorInfo().colorType());
142 
143     DeviceFlags flags;
144     if (!rContext->colorTypeSupportedAsSurface(ct) ||
145         !CheckAlphaTypeAndGetFlags(alphaType, init, &flags)) {
146         return nullptr;
147     }
148     return sk_sp<Device>(new Device(std::move(sdc), flags));
149 }
150 
Make(GrRecordingContext * rContext,SkBudgeted budgeted,const SkImageInfo & ii,SkBackingFit fit,int sampleCount,GrMipmapped mipMapped,GrProtected isProtected,GrSurfaceOrigin origin,const SkSurfaceProps & props,InitContents init)151 sk_sp<BaseDevice> Device::Make(GrRecordingContext* rContext,
152                                SkBudgeted budgeted,
153                                const SkImageInfo& ii,
154                                SkBackingFit fit,
155                                int sampleCount,
156                                GrMipmapped mipMapped,
157                                GrProtected isProtected,
158                                GrSurfaceOrigin origin,
159                                const SkSurfaceProps& props,
160                                InitContents init) {
161     if (!rContext) {
162         return nullptr;
163     }
164 
165     auto sdc = SurfaceDrawContext::Make(rContext,
166                                         SkColorTypeToGrColorType(ii.colorType()),
167                                         ii.refColorSpace(),
168                                         fit,
169                                         ii.dimensions(),
170                                         props,
171                                         sampleCount,
172                                         mipMapped,
173                                         isProtected,
174                                         origin,
175                                         budgeted);
176 
177     return Device::Make(std::move(sdc), ii.alphaType(), init);
178 }
179 
Device(std::unique_ptr<SurfaceDrawContext> sdc,DeviceFlags flags)180 Device::Device(std::unique_ptr<SurfaceDrawContext> sdc, DeviceFlags flags)
181         : INHERITED(sk_ref_sp(sdc->recordingContext()),
182                     MakeInfo(sdc.get(), flags),
183                     sdc->surfaceProps())
184         , fSurfaceDrawContext(std::move(sdc))
185         , fClip(SkIRect::MakeSize(fSurfaceDrawContext->dimensions()),
186                 &this->asMatrixProvider(),
187                 force_aa_clip(fSurfaceDrawContext.get())) {
188     if (flags & DeviceFlags::kNeedClear) {
189         this->clearAll();
190     }
191 }
192 
193 ///////////////////////////////////////////////////////////////////////////////
194 
onReadPixels(const SkPixmap & pm,int x,int y)195 bool Device::onReadPixels(const SkPixmap& pm, int x, int y) {
196     ASSERT_SINGLE_OWNER
197 
198     // Context TODO: Elevate direct context requirement to public API
199     auto dContext = fContext->asDirectContext();
200     if (!dContext || !SkImageInfoValidConversion(pm.info(), this->imageInfo())) {
201         return false;
202     }
203 
204     return fSurfaceDrawContext->readPixels(dContext, pm, {x, y});
205 }
206 
onWritePixels(const SkPixmap & pm,int x,int y)207 bool Device::onWritePixels(const SkPixmap& pm, int x, int y) {
208     ASSERT_SINGLE_OWNER
209 
210     // Context TODO: Elevate direct context requirement to public API
211     auto dContext = fContext->asDirectContext();
212     if (!dContext || !SkImageInfoValidConversion(this->imageInfo(), pm.info())) {
213         return false;
214     }
215 
216     return fSurfaceDrawContext->writePixels(dContext, pm, {x, y});
217 }
218 
onAccessPixels(SkPixmap * pmap)219 bool Device::onAccessPixels(SkPixmap* pmap) {
220     ASSERT_SINGLE_OWNER
221     return false;
222 }
223 
surfaceDrawContext()224 SurfaceDrawContext* Device::surfaceDrawContext() {
225     ASSERT_SINGLE_OWNER
226     return fSurfaceDrawContext.get();
227 }
228 
surfaceDrawContext() const229 const SurfaceDrawContext* Device::surfaceDrawContext() const {
230     ASSERT_SINGLE_OWNER
231     return fSurfaceDrawContext.get();
232 }
233 
surfaceFillContext()234 skgpu::SurfaceFillContext* Device::surfaceFillContext() {
235     ASSERT_SINGLE_OWNER
236     return fSurfaceDrawContext.get();
237 }
238 
clearAll()239 void Device::clearAll() {
240     ASSERT_SINGLE_OWNER
241     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "clearAll", fContext.get());
242 
243     SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
244     fSurfaceDrawContext->clearAtLeast(rect, SK_PMColor4fTRANSPARENT);
245 }
246 
247 ///////////////////////////////////////////////////////////////////////////////
248 
onClipPath(const SkPath & path,SkClipOp op,bool aa)249 void Device::onClipPath(const SkPath& path, SkClipOp op, bool aa) {
250 #if GR_TEST_UTILS
251     if (fContext->priv().options().fAllPathsVolatile && !path.isVolatile()) {
252         this->onClipPath(SkPath(path).setIsVolatile(true), op, aa);
253         return;
254     }
255 #endif
256     SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference);
257     fClip.clipPath(this->localToDevice(), path, GrAA(aa), op);
258 }
259 
onClipRegion(const SkRegion & globalRgn,SkClipOp op)260 void Device::onClipRegion(const SkRegion& globalRgn, SkClipOp op) {
261     SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference);
262 
263     // Regions don't actually need AA, but in DMSAA mode every clip element is antialiased.
264     GrAA aa = GrAA(fSurfaceDrawContext->alwaysAntialias());
265 
266     if (globalRgn.isEmpty()) {
267         fClip.clipRect(SkMatrix::I(), SkRect::MakeEmpty(), aa, op);
268     } else if (globalRgn.isRect()) {
269         fClip.clipRect(this->globalToDevice().asM33(), SkRect::Make(globalRgn.getBounds()), aa, op);
270     } else {
271         SkPath path;
272         globalRgn.getBoundaryPath(&path);
273         fClip.clipPath(this->globalToDevice().asM33(), path, aa, op);
274     }
275 }
276 
onAsRgnClip(SkRegion * region) const277 void Device::onAsRgnClip(SkRegion* region) const {
278     SkIRect bounds = fClip.getConservativeBounds();
279     // Assume wide open and then perform intersect/difference operations reducing the region
280     region->setRect(bounds);
281     const SkRegion deviceBounds(bounds);
282     for (const ClipStack::Element& e : fClip) {
283         SkRegion tmp;
284         if (e.fShape.isRect() && e.fLocalToDevice.isIdentity()) {
285             tmp.setRect(e.fShape.rect().roundOut());
286         } else {
287             SkPath tmpPath;
288             e.fShape.asPath(&tmpPath);
289             tmpPath.transform(e.fLocalToDevice);
290             tmp.setPath(tmpPath, deviceBounds);
291         }
292 
293         region->op(tmp, (SkRegion::Op) e.fOp);
294     }
295 }
296 
onClipIsAA() const297 bool Device::onClipIsAA() const {
298     for (const ClipStack::Element& e : fClip) {
299         if (e.fAA == GrAA::kYes) {
300             return true;
301         }
302         SkASSERT(!fSurfaceDrawContext->alwaysAntialias());
303     }
304     return false;
305 }
306 
onGetClipType() const307 SkBaseDevice::ClipType Device::onGetClipType() const {
308     ClipStack::ClipState state = fClip.clipState();
309     if (state == ClipStack::ClipState::kEmpty) {
310         return ClipType::kEmpty;
311     } else if (state == ClipStack::ClipState::kDeviceRect ||
312                state == ClipStack::ClipState::kWideOpen) {
313         return ClipType::kRect;
314     } else {
315         return ClipType::kComplex;
316     }
317 }
318 
319 ///////////////////////////////////////////////////////////////////////////////
320 
drawPaint(const SkPaint & paint)321 void Device::drawPaint(const SkPaint& paint) {
322     ASSERT_SINGLE_OWNER
323     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPaint", fContext.get());
324 
325     GrPaint grPaint;
326     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
327                           this->asMatrixProvider(), &grPaint)) {
328         return;
329     }
330 
331     fSurfaceDrawContext->drawPaint(this->clip(), std::move(grPaint), this->localToDevice());
332 }
333 
drawPoints(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)334 void Device::drawPoints(SkCanvas::PointMode mode,
335                         size_t count,
336                         const SkPoint pts[],
337                         const SkPaint& paint) {
338     ASSERT_SINGLE_OWNER
339     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPoints", fContext.get());
340     SkScalar width = paint.getStrokeWidth();
341     if (width < 0) {
342         return;
343     }
344 
345     GrAA aa = fSurfaceDrawContext->chooseAA(paint);
346 
347     if (count == 2 && mode == SkCanvas::kLines_PointMode) {
348         if (paint.getPathEffect()) {
349             // Probably a dashed line. Draw as a path.
350             GrPaint grPaint;
351             if (SkPaintToGrPaint(this->recordingContext(),
352                                   fSurfaceDrawContext->colorInfo(),
353                                   paint,
354                                   this->asMatrixProvider(),
355                                   &grPaint)) {
356                 SkPath path;
357                 path.setIsVolatile(true);
358                 path.moveTo(pts[0]);
359                 path.lineTo(pts[1]);
360                 fSurfaceDrawContext->drawPath(this->clip(),
361                                               std::move(grPaint),
362                                               aa,
363                                               this->localToDevice(),
364                                               path,
365                                               GrStyle(paint, SkPaint::kStroke_Style));
366             }
367             return;
368         }
369         if (!paint.getMaskFilter() &&
370             paint.getStrokeWidth() > 0 &&  // drawStrokedLine doesn't support hairlines.
371             paint.getStrokeCap() != SkPaint::kRound_Cap) { // drawStrokedLine doesn't do round caps.
372             // Simple stroked line. Bypass path rendering.
373             GrPaint grPaint;
374             if (SkPaintToGrPaint(this->recordingContext(),
375                                  fSurfaceDrawContext->colorInfo(),
376                                  paint,
377                                  this->asMatrixProvider(),
378                                  &grPaint)) {
379                 fSurfaceDrawContext->drawStrokedLine(this->clip(),
380                                                      std::move(grPaint),
381                                                      aa,
382                                                      this->localToDevice(),
383                                                      pts,
384                                                      SkStrokeRec(paint, SkPaint::kStroke_Style));
385             }
386             return;
387         }
388     }
389 
390     SkScalar scales[2];
391     bool isHairline = (0 == width) ||
392                        (1 == width && this->localToDevice().getMinMaxScales(scales) &&
393                         SkScalarNearlyEqual(scales[0], 1.f) && SkScalarNearlyEqual(scales[1], 1.f));
394     // we only handle non-coverage-aa hairlines and paints without path effects or mask filters,
395     // else we let the SkDraw call our drawPath()
396     if (!isHairline ||
397         paint.getPathEffect() ||
398         paint.getMaskFilter() ||
399         fSurfaceDrawContext->chooseAAType(aa) == GrAAType::kCoverage) {
400         SkRasterClip rc(this->devClipBounds());
401         SkDraw draw;
402         draw.fDst = SkPixmap(SkImageInfo::MakeUnknown(this->width(), this->height()), nullptr, 0);
403         draw.fMatrixProvider = this;
404         draw.fRC = &rc;
405         draw.drawPoints(mode, count, pts, paint, this);
406         return;
407     }
408 
409     GrPrimitiveType primitiveType = point_mode_to_primitive_type(mode);
410 
411     const SkMatrixProvider* matrixProvider = this;
412 
413     GrPaint grPaint;
414     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
415                           *matrixProvider, &grPaint)) {
416         return;
417     }
418 
419     static constexpr SkVertices::VertexMode kIgnoredMode = SkVertices::kTriangles_VertexMode;
420     sk_sp<SkVertices> vertices = SkVertices::MakeCopy(kIgnoredMode, SkToS32(count), pts, nullptr,
421                                                       nullptr);
422 
423     fSurfaceDrawContext->drawVertices(this->clip(), std::move(grPaint), *matrixProvider,
424                                       std::move(vertices), &primitiveType);
425 }
426 
427 ///////////////////////////////////////////////////////////////////////////////
428 
drawRect(const SkRect & rect,const SkPaint & paint)429 void Device::drawRect(const SkRect& rect, const SkPaint& paint) {
430     ASSERT_SINGLE_OWNER
431     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawRect", fContext.get());
432 
433     GrStyle style(paint);
434 
435     // A couple reasons we might need to call drawPath.
436     if (paint.getMaskFilter() || paint.getPathEffect()) {
437         GrStyledShape shape(rect, style);
438 
439         GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(),
440                                              this->clip(), paint, this->asMatrixProvider(), shape);
441         return;
442     }
443 
444     GrPaint grPaint;
445     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
446                           this->asMatrixProvider(), &grPaint)) {
447         return;
448     }
449 
450     fSurfaceDrawContext->drawRect(this->clip(), std::move(grPaint),
451                                   fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), rect,
452                                   &style);
453 }
454 
drawEdgeAAQuad(const SkRect & rect,const SkPoint clip[4],SkCanvas::QuadAAFlags aaFlags,const SkColor4f & color,SkBlendMode mode)455 void Device::drawEdgeAAQuad(const SkRect& rect,
456                             const SkPoint clip[4],
457                             SkCanvas::QuadAAFlags aaFlags,
458                             const SkColor4f& color,
459                             SkBlendMode mode) {
460     ASSERT_SINGLE_OWNER
461     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawEdgeAAQuad", fContext.get());
462 
463     SkPMColor4f dstColor = SkColor4fPrepForDst(color, fSurfaceDrawContext->colorInfo()).premul();
464 
465     GrPaint grPaint;
466     grPaint.setColor4f(dstColor);
467     if (mode != SkBlendMode::kSrcOver) {
468         grPaint.setXPFactory(SkBlendMode_AsXPFactory(mode));
469     }
470 
471     // This is exclusively meant for tiling operations, so keep AA enabled to handle MSAA seaming
472     GrQuadAAFlags grAA = SkToGrQuadAAFlags(aaFlags);
473     if (clip) {
474         // Use fillQuadWithEdgeAA
475         fSurfaceDrawContext->fillQuadWithEdgeAA(this->clip(), std::move(grPaint), GrAA::kYes, grAA,
476                                                 this->localToDevice(), clip, nullptr);
477     } else {
478         // Use fillRectWithEdgeAA to preserve mathematical properties of dst being rectangular
479         fSurfaceDrawContext->fillRectWithEdgeAA(this->clip(), std::move(grPaint), GrAA::kYes, grAA,
480                                                 this->localToDevice(), rect);
481     }
482 }
483 
484 ///////////////////////////////////////////////////////////////////////////////
485 
drawRRect(const SkRRect & rrect,const SkPaint & paint)486 void Device::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
487     ASSERT_SINGLE_OWNER
488     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawRRect", fContext.get());
489 
490     SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter());
491     if (mf) {
492         if (mf->hasFragmentProcessor()) {
493             mf = nullptr; // already handled in SkPaintToGrPaint
494         }
495     }
496 
497     GrStyle style(paint);
498 
499     if (mf || style.pathEffect()) {
500         // A path effect will presumably transform this rrect into something else.
501         GrStyledShape shape(rrect, style);
502 
503         GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(),
504                                              this->clip(), paint, this->asMatrixProvider(), shape);
505         return;
506     }
507 
508     SkASSERT(!style.pathEffect());
509 
510     GrPaint grPaint;
511     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
512                           this->asMatrixProvider(), &grPaint)) {
513         return;
514     }
515 
516     fSurfaceDrawContext->drawRRect(this->clip(), std::move(grPaint),
517                                    fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
518                                    rrect, style);
519 }
520 
drawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)521 void Device::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
522     ASSERT_SINGLE_OWNER
523     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawDRRect", fContext.get());
524     if (outer.isEmpty()) {
525        return;
526     }
527 
528     if (inner.isEmpty()) {
529         return this->drawRRect(outer, paint);
530     }
531 
532     SkStrokeRec stroke(paint);
533 
534     if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) {
535         // For axis-aligned filled DRRects, just draw a regular rrect with inner clipped out using a
536         // coverage FP instead of using path rendering.
537         if (auto fp = make_inverse_rrect_fp(this->localToDevice(), inner,
538                                             fSurfaceDrawContext->chooseAA(paint),
539                                             *fSurfaceDrawContext->caps()->shaderCaps())) {
540             GrPaint grPaint;
541             if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
542                                   this->asMatrixProvider(), &grPaint)) {
543                 return;
544             }
545             SkASSERT(!grPaint.hasCoverageFragmentProcessor());
546             grPaint.setCoverageFragmentProcessor(std::move(fp));
547             fSurfaceDrawContext->drawRRect(this->clip(), std::move(grPaint),
548                                            fSurfaceDrawContext->chooseAA(paint),
549                                            this->localToDevice(), outer, GrStyle());
550             return;
551         }
552     }
553 
554     SkPath path;
555     path.setIsVolatile(true);
556     path.addRRect(outer);
557     path.addRRect(inner);
558     path.setFillType(SkPathFillType::kEvenOdd);
559 
560     // TODO: We are losing the possible mutability of the path here but this should probably be
561     // fixed by upgrading GrStyledShape to handle DRRects.
562     GrStyledShape shape(path, paint);
563 
564     GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), this->clip(),
565                                          paint, this->asMatrixProvider(), shape);
566 }
567 
568 /////////////////////////////////////////////////////////////////////////////
569 
drawRegion(const SkRegion & region,const SkPaint & paint)570 void Device::drawRegion(const SkRegion& region, const SkPaint& paint) {
571     ASSERT_SINGLE_OWNER
572 
573     if (paint.getMaskFilter()) {
574         SkPath path;
575         region.getBoundaryPath(&path);
576         path.setIsVolatile(true);
577         return this->drawPath(path, paint, true);
578     }
579 
580     GrPaint grPaint;
581     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
582                           this->asMatrixProvider(), &grPaint)) {
583         return;
584     }
585 
586     fSurfaceDrawContext->drawRegion(this->clip(), std::move(grPaint),
587                                     fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
588                                     region, GrStyle(paint));
589 }
590 
drawOval(const SkRect & oval,const SkPaint & paint)591 void Device::drawOval(const SkRect& oval, const SkPaint& paint) {
592     ASSERT_SINGLE_OWNER
593     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawOval", fContext.get());
594 
595     if (paint.getMaskFilter()) {
596         // The RRect path can handle special case blurring
597         SkRRect rr = SkRRect::MakeOval(oval);
598         return this->drawRRect(rr, paint);
599     }
600 
601     GrPaint grPaint;
602     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
603                           this->asMatrixProvider(), &grPaint)) {
604         return;
605     }
606 
607     fSurfaceDrawContext->drawOval(this->clip(), std::move(grPaint),
608                                   fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), oval,
609                                   GrStyle(paint));
610 }
611 
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)612 void Device::drawArc(const SkRect& oval,
613                      SkScalar startAngle,
614                      SkScalar sweepAngle,
615                      bool useCenter,
616                      const SkPaint& paint) {
617     ASSERT_SINGLE_OWNER
618     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawArc", fContext.get());
619     if (paint.getMaskFilter()) {
620         this->INHERITED::drawArc(oval, startAngle, sweepAngle, useCenter, paint);
621         return;
622     }
623     GrPaint grPaint;
624     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
625                           this->asMatrixProvider(), &grPaint)) {
626         return;
627     }
628 
629     fSurfaceDrawContext->drawArc(this->clip(), std::move(grPaint),
630                                  fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), oval,
631                                  startAngle, sweepAngle, useCenter, GrStyle(paint));
632 }
633 
634 ///////////////////////////////////////////////////////////////////////////////
635 
drawPath(const SkPath & origSrcPath,const SkPaint & paint,bool pathIsMutable)636 void Device::drawPath(const SkPath& origSrcPath, const SkPaint& paint, bool pathIsMutable) {
637 #if GR_TEST_UTILS
638     if (fContext->priv().options().fAllPathsVolatile && !origSrcPath.isVolatile()) {
639         this->drawPath(SkPath(origSrcPath).setIsVolatile(true), paint, true);
640         return;
641     }
642 #endif
643     ASSERT_SINGLE_OWNER
644     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPath", fContext.get());
645     if (!paint.getMaskFilter()) {
646         GrPaint grPaint;
647         if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
648                               this->asMatrixProvider(), &grPaint)) {
649             return;
650         }
651         fSurfaceDrawContext->drawPath(this->clip(), std::move(grPaint),
652                                       fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
653                                       origSrcPath, GrStyle(paint));
654         return;
655     }
656 
657     // TODO: losing possible mutability of 'origSrcPath' here
658     GrStyledShape shape(origSrcPath, paint);
659 
660     GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), this->clip(),
661                                          paint, this->asMatrixProvider(), shape);
662 }
663 
makeSpecial(const SkBitmap & bitmap)664 sk_sp<SkSpecialImage> Device::makeSpecial(const SkBitmap& bitmap) {
665     ASSERT_SINGLE_OWNER
666 
667     // TODO: this makes a tight copy of 'bitmap' but it doesn't have to be (given SkSpecialImage's
668     // semantics). Since this is cached we would have to bake the fit into the cache key though.
669     auto view = std::get<0>(GrMakeCachedBitmapProxyView(fContext.get(), bitmap));
670     if (!view) {
671         return nullptr;
672     }
673 
674     const SkIRect rect = SkIRect::MakeSize(view.proxy()->dimensions());
675 
676     // GrMakeCachedBitmapProxyView creates a tight copy of 'bitmap' so we don't have to subset
677     // the special image
678     return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
679                                                rect,
680                                                bitmap.getGenerationID(),
681                                                std::move(view),
682                                                SkColorTypeToGrColorType(bitmap.colorType()),
683                                                bitmap.refColorSpace(),
684                                                this->surfaceProps());
685 }
686 
makeSpecial(const SkImage * image)687 sk_sp<SkSpecialImage> Device::makeSpecial(const SkImage* image) {
688     ASSERT_SINGLE_OWNER
689 
690     SkPixmap pm;
691     if (image->isTextureBacked()) {
692         auto [view, ct] = as_IB(image)->asView(this->recordingContext(), GrMipmapped::kNo);
693         SkASSERT(view);
694 
695         return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
696                                                    SkIRect::MakeWH(image->width(), image->height()),
697                                                    image->uniqueID(),
698                                                    std::move(view),
699                                                    ct,
700                                                    image->refColorSpace(),
701                                                    this->surfaceProps());
702     } else if (image->peekPixels(&pm)) {
703         SkBitmap bm;
704 
705         bm.installPixels(pm);
706         return this->makeSpecial(bm);
707     } else {
708         return nullptr;
709     }
710 }
711 
snapSpecial(const SkIRect & subset,bool forceCopy)712 sk_sp<SkSpecialImage> Device::snapSpecial(const SkIRect& subset, bool forceCopy) {
713     ASSERT_SINGLE_OWNER
714 
715     auto sdc = fSurfaceDrawContext.get();
716 
717     // If we are wrapping a vulkan secondary command buffer, then we can't snap off a special image
718     // since it would require us to make a copy of the underlying VkImage which we don't have access
719     // to. Additionaly we can't stop and start the render pass that is used with the secondary
720     // command buffer.
721     if (sdc->wrapsVkSecondaryCB()) {
722         return nullptr;
723     }
724 
725     SkASSERT(sdc->asSurfaceProxy());
726 
727     SkIRect finalSubset = subset;
728     GrSurfaceProxyView view = sdc->readSurfaceView();
729     if (forceCopy || !view.asTextureProxy()) {
730         // When the device doesn't have a texture, or a copy is requested, we create a temporary
731         // texture that matches the device contents
732         view = GrSurfaceProxyView::Copy(fContext.get(),
733                                         std::move(view),
734                                         GrMipmapped::kNo,  // Don't auto generate mips
735                                         subset,
736                                         SkBackingFit::kApprox,
737                                         SkBudgeted::kYes);  // Always budgeted
738         if (!view) {
739             return nullptr;
740         }
741         // Since this copied only the requested subset, the special image wrapping the proxy no
742         // longer needs the original subset.
743         finalSubset = SkIRect::MakeSize(view.dimensions());
744     }
745 
746     GrColorType ct = SkColorTypeToGrColorType(this->imageInfo().colorType());
747 
748     return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
749                                                finalSubset,
750                                                kNeedNewImageUniqueID_SpecialImage,
751                                                std::move(view),
752                                                ct,
753                                                this->imageInfo().refColorSpace(),
754                                                this->surfaceProps());
755 }
756 
drawDevice(SkBaseDevice * device,const SkSamplingOptions & sampling,const SkPaint & paint)757 void Device::drawDevice(SkBaseDevice* device,
758                         const SkSamplingOptions& sampling,
759                         const SkPaint& paint) {
760     ASSERT_SINGLE_OWNER
761     // clear of the source device must occur before CHECK_SHOULD_DRAW
762     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawDevice", fContext.get());
763     this->INHERITED::drawDevice(device, sampling, paint);
764 }
765 
drawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint & paint,SkCanvas::SrcRectConstraint constraint)766 void Device::drawImageRect(const SkImage* image,
767                            const SkRect* src,
768                            const SkRect& dst,
769                            const SkSamplingOptions& sampling,
770                            const SkPaint& paint,
771                            SkCanvas::SrcRectConstraint constraint) {
772     ASSERT_SINGLE_OWNER
773     GrAA aa = fSurfaceDrawContext->chooseAA(paint);
774     GrQuadAAFlags aaFlags = (aa == GrAA::kYes) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
775     this->drawImageQuad(image, src, &dst, nullptr, aa, aaFlags, nullptr, sampling, paint,
776                         constraint);
777 }
778 
drawViewLattice(GrSurfaceProxyView view,const GrColorInfo & info,std::unique_ptr<SkLatticeIter> iter,const SkRect & dst,SkFilterMode filter,const SkPaint & origPaint)779 void Device::drawViewLattice(GrSurfaceProxyView view,
780                              const GrColorInfo& info,
781                              std::unique_ptr<SkLatticeIter> iter,
782                              const SkRect& dst,
783                              SkFilterMode filter,
784                              const SkPaint& origPaint) {
785     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawViewLattice", fContext.get());
786     SkASSERT(view);
787 
788     SkTCopyOnFirstWrite<SkPaint> paint(&origPaint);
789 
790     if (!info.isAlphaOnly() && (paint->getColor() & 0x00FFFFFF) != 0x00FFFFFF) {
791         paint.writable()->setColor(SkColorSetARGB(origPaint.getAlpha(), 0xFF, 0xFF, 0xFF));
792     }
793     GrPaint grPaint;
794     // Passing null as shaderFP indicates that the GP will provide the shader.
795     if (!SkPaintToGrPaintReplaceShader(this->recordingContext(),
796                                        fSurfaceDrawContext->colorInfo(),
797                                        *paint,
798                                        this->asMatrixProvider(),
799                                        /*shaderFP=*/nullptr,
800                                        &grPaint)) {
801         return;
802     }
803 
804     if (info.isAlphaOnly()) {
805         // If we were doing this with an FP graph we'd use a kDstIn blend between the texture and
806         // the paint color.
807         view.concatSwizzle(skgpu::Swizzle("aaaa"));
808     }
809     auto csxf = GrColorSpaceXform::Make(info, fSurfaceDrawContext->colorInfo());
810 
811     fSurfaceDrawContext->drawImageLattice(this->clip(), std::move(grPaint), this->localToDevice(),
812                                           std::move(view), info.alphaType(), std::move(csxf),
813                                           filter, std::move(iter), dst);
814 }
815 
drawImageLattice(const SkImage * image,const SkCanvas::Lattice & lattice,const SkRect & dst,SkFilterMode filter,const SkPaint & paint)816 void Device::drawImageLattice(const SkImage* image,
817                               const SkCanvas::Lattice& lattice,
818                               const SkRect& dst,
819                               SkFilterMode filter,
820                               const SkPaint& paint) {
821     ASSERT_SINGLE_OWNER
822     auto iter = std::make_unique<SkLatticeIter>(lattice, dst);
823     if (auto [view, ct] = as_IB(image)->asView(this->recordingContext(), GrMipmapped::kNo); view) {
824         GrColorInfo colorInfo(ct, image->alphaType(), image->refColorSpace());
825         this->drawViewLattice(std::move(view),
826                               std::move(colorInfo),
827                               std::move(iter),
828                               dst,
829                               filter,
830                               paint);
831     }
832 }
833 
drawVertices(const SkVertices * vertices,sk_sp<SkBlender> blender,const SkPaint & paint)834 void Device::drawVertices(const SkVertices* vertices,
835                           sk_sp<SkBlender> blender,
836                           const SkPaint& paint) {
837     ASSERT_SINGLE_OWNER
838     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawVertices", fContext.get());
839     SkASSERT(vertices);
840 
841 #ifdef SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER
842     if (!paint.getShader()) {
843         blender = SkBlender::Mode(SkBlendMode::kDst);
844     }
845 #endif
846 
847     SkVerticesPriv info(vertices->priv());
848 
849     GrPaint grPaint;
850     if (!init_vertices_paint(fContext.get(),
851                              fSurfaceDrawContext->colorInfo(),
852                              paint,
853                              this->asMatrixProvider(),
854                              std::move(blender),
855                              info.hasColors(),
856                              &grPaint)) {
857         return;
858     }
859     fSurfaceDrawContext->drawVertices(this->clip(),
860                                       std::move(grPaint),
861                                       this->asMatrixProvider(),
862                                       sk_ref_sp(const_cast<SkVertices*>(vertices)),
863                                       nullptr);
864 }
865 
drawCustomMesh(SkCustomMesh customMesh,sk_sp<SkBlender> blender,const SkPaint & paint)866 void Device::drawCustomMesh(SkCustomMesh customMesh,
867                             sk_sp<SkBlender> blender,
868                             const SkPaint& paint) {
869     ASSERT_SINGLE_OWNER
870     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawCustomMesh", fContext.get());
871     SkASSERT(customMesh.vb);
872 
873     GrPaint grPaint;
874     if (!init_vertices_paint(fContext.get(),
875                              fSurfaceDrawContext->colorInfo(),
876                              paint,
877                              this->asMatrixProvider(),
878                              std::move(blender),
879                              SkCustomMeshSpecificationPriv::HasColors(*customMesh.spec),
880                              &grPaint)) {
881         return;
882     }
883     fSurfaceDrawContext->drawCustomMesh(this->clip(),
884                                         std::move(grPaint),
885                                         this->asMatrixProvider(),
886                                         std::move(customMesh));
887 }
888 
889 ///////////////////////////////////////////////////////////////////////////////
890 
drawShadow(const SkPath & path,const SkDrawShadowRec & rec)891 void Device::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
892 #if GR_TEST_UTILS
893     if (fContext->priv().options().fAllPathsVolatile && !path.isVolatile()) {
894         this->drawShadow(SkPath(path).setIsVolatile(true), rec);
895         return;
896     }
897 #endif
898     ASSERT_SINGLE_OWNER
899     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawShadow", fContext.get());
900 
901     if (!fSurfaceDrawContext->drawFastShadow(this->clip(), this->localToDevice(), path, rec)) {
902         // failed to find an accelerated case
903         this->INHERITED::drawShadow(path, rec);
904     }
905 }
906 
907 ///////////////////////////////////////////////////////////////////////////////
908 
drawAtlas(const SkRSXform xform[],const SkRect texRect[],const SkColor colors[],int count,sk_sp<SkBlender> blender,const SkPaint & paint)909 void Device::drawAtlas(const SkRSXform xform[],
910                        const SkRect texRect[],
911                        const SkColor colors[],
912                        int count,
913                        sk_sp<SkBlender> blender,
914                        const SkPaint& paint) {
915     ASSERT_SINGLE_OWNER
916     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawAtlas", fContext.get());
917 
918     GrPaint grPaint;
919     if (colors) {
920         if (!SkPaintToGrPaintWithBlend(this->recordingContext(),
921                                        fSurfaceDrawContext->colorInfo(),
922                                        paint,
923                                        this->asMatrixProvider(),
924                                        blender.get(),
925                                        &grPaint)) {
926             return;
927         }
928     } else {
929         if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(),
930                               paint, this->asMatrixProvider(), &grPaint)) {
931             return;
932         }
933     }
934 
935     fSurfaceDrawContext->drawAtlas(this->clip(), std::move(grPaint), this->localToDevice(), count,
936                                    xform, texRect, colors);
937 }
938 
939 ///////////////////////////////////////////////////////////////////////////////
940 
onDrawGlyphRunList(SkCanvas * canvas,const SkGlyphRunList & glyphRunList,const SkPaint & paint)941 void Device::onDrawGlyphRunList(SkCanvas* canvas,
942                                 const SkGlyphRunList& glyphRunList,
943                                 const SkPaint& paint) {
944     ASSERT_SINGLE_OWNER
945     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawGlyphRunList", fContext.get());
946     SkASSERT(!glyphRunList.hasRSXForm());
947 
948     #if defined(SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG)
949         auto slug = this->convertGlyphRunListToSlug(glyphRunList, paint);
950         if (slug != nullptr) {
951             this->drawSlug(slug.get());
952         }
953         return;
954     #endif
955 
956     fSurfaceDrawContext->drawGlyphRunList(
957         canvas, this->clip(), this->asMatrixProvider(), glyphRunList, paint);
958 }
959 
960 ///////////////////////////////////////////////////////////////////////////////
961 
drawDrawable(SkCanvas * canvas,SkDrawable * drawable,const SkMatrix * matrix)962 void Device::drawDrawable(SkCanvas* canvas, SkDrawable* drawable, const SkMatrix* matrix) {
963     ASSERT_SINGLE_OWNER
964 
965     GrBackendApi api = this->recordingContext()->backend();
966     if (GrBackendApi::kVulkan == api) {
967         const SkMatrix& ctm = this->localToDevice();
968         const SkMatrix& combinedMatrix = matrix ? SkMatrix::Concat(ctm, *matrix) : ctm;
969         std::unique_ptr<SkDrawable::GpuDrawHandler> gpuDraw =
970                 drawable->snapGpuDrawHandler(api, combinedMatrix, this->devClipBounds(),
971                                              this->imageInfo());
972         if (gpuDraw) {
973             fSurfaceDrawContext->drawDrawable(
974                     std::move(gpuDraw), combinedMatrix.mapRect(drawable->getBounds()));
975             return;
976         }
977     }
978     this->INHERITED::drawDrawable(canvas, drawable, matrix);
979 }
980 
981 
982 ///////////////////////////////////////////////////////////////////////////////
983 
wait(int numSemaphores,const GrBackendSemaphore * waitSemaphores,bool deleteSemaphoresAfterWait)984 bool Device::wait(int numSemaphores,
985                   const GrBackendSemaphore* waitSemaphores,
986                   bool deleteSemaphoresAfterWait) {
987     ASSERT_SINGLE_OWNER
988 
989     return fSurfaceDrawContext->waitOnSemaphores(numSemaphores, waitSemaphores,
990                                                  deleteSemaphoresAfterWait);
991 }
992 
replaceBackingProxy(SkSurface::ContentChangeMode mode,sk_sp<GrRenderTargetProxy> newRTP,GrColorType grColorType,sk_sp<SkColorSpace> colorSpace,GrSurfaceOrigin origin,const SkSurfaceProps & props)993 bool Device::replaceBackingProxy(SkSurface::ContentChangeMode mode,
994                                  sk_sp<GrRenderTargetProxy> newRTP,
995                                  GrColorType grColorType,
996                                  sk_sp<SkColorSpace> colorSpace,
997                                  GrSurfaceOrigin origin,
998                                  const SkSurfaceProps& props) {
999     auto sdc = SurfaceDrawContext::Make(fContext.get(), grColorType, std::move(newRTP),
1000                                         std::move(colorSpace), origin, props);
1001     if (!sdc) {
1002         return false;
1003     }
1004 
1005     SkASSERT(sdc->dimensions() == fSurfaceDrawContext->dimensions());
1006     SkASSERT(sdc->numSamples() == fSurfaceDrawContext->numSamples());
1007     SkASSERT(sdc->asSurfaceProxy()->priv().isExact());
1008     if (mode == SkSurface::kRetain_ContentChangeMode) {
1009         if (fContext->abandoned()) {
1010             return false;
1011         }
1012 
1013         SkASSERT(fSurfaceDrawContext->asTextureProxy());
1014         SkAssertResult(sdc->blitTexture(fSurfaceDrawContext->readSurfaceView(),
1015                                         SkIRect::MakeWH(this->width(), this->height()),
1016                                         SkIPoint::Make(0, 0)));
1017     }
1018 
1019     fSurfaceDrawContext = std::move(sdc);
1020     return true;
1021 }
1022 
asyncRescaleAndReadPixels(const SkImageInfo & info,const SkIRect & srcRect,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)1023 void Device::asyncRescaleAndReadPixels(const SkImageInfo& info,
1024                                        const SkIRect& srcRect,
1025                                        RescaleGamma rescaleGamma,
1026                                        RescaleMode rescaleMode,
1027                                        ReadPixelsCallback callback,
1028                                        ReadPixelsContext context) {
1029     auto* sdc = fSurfaceDrawContext.get();
1030     // Context TODO: Elevate direct context requirement to public API.
1031     auto dContext = sdc->recordingContext()->asDirectContext();
1032     if (!dContext) {
1033         return;
1034     }
1035     sdc->asyncRescaleAndReadPixels(dContext, info, srcRect, rescaleGamma, rescaleMode, callback,
1036                                    context);
1037 }
1038 
asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,SkISize dstSize,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)1039 void Device::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
1040                                              sk_sp<SkColorSpace> dstColorSpace,
1041                                              const SkIRect& srcRect,
1042                                              SkISize dstSize,
1043                                              RescaleGamma rescaleGamma,
1044                                              RescaleMode rescaleMode,
1045                                              ReadPixelsCallback callback,
1046                                              ReadPixelsContext context) {
1047     auto* sdc = fSurfaceDrawContext.get();
1048     // Context TODO: Elevate direct context requirement to public API.
1049     auto dContext = sdc->recordingContext()->asDirectContext();
1050     if (!dContext) {
1051         return;
1052     }
1053     sdc->asyncRescaleAndReadPixelsYUV420(dContext,
1054                                          yuvColorSpace,
1055                                          std::move(dstColorSpace),
1056                                          srcRect,
1057                                          dstSize,
1058                                          rescaleGamma,
1059                                          rescaleMode,
1060                                          callback,
1061                                          context);
1062 }
1063 
1064 ///////////////////////////////////////////////////////////////////////////////
1065 
onCreateDevice(const CreateInfo & cinfo,const SkPaint *)1066 SkBaseDevice* Device::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
1067     ASSERT_SINGLE_OWNER
1068 
1069     SkSurfaceProps props(this->surfaceProps().flags(), cinfo.fPixelGeometry);
1070 
1071     // layers are never drawn in repeat modes, so we can request an approx
1072     // match and ignore any padding.
1073     SkBackingFit fit = kNever_TileUsage == cinfo.fTileUsage ? SkBackingFit::kApprox
1074                                                             : SkBackingFit::kExact;
1075 
1076     SkASSERT(cinfo.fInfo.colorType() != kRGBA_1010102_SkColorType);
1077 
1078     auto sdc = SurfaceDrawContext::MakeWithFallback(
1079             fContext.get(), SkColorTypeToGrColorType(cinfo.fInfo.colorType()),
1080             fSurfaceDrawContext->colorInfo().refColorSpace(), fit, cinfo.fInfo.dimensions(), props,
1081             fSurfaceDrawContext->numSamples(), GrMipmapped::kNo,
1082             fSurfaceDrawContext->asSurfaceProxy()->isProtected(),
1083             fSurfaceDrawContext->origin(),
1084             SkBudgeted::kYes);
1085     if (!sdc) {
1086         return nullptr;
1087     }
1088 
1089     // Skia's convention is to only clear a device if it is non-opaque.
1090     InitContents init = cinfo.fInfo.isOpaque() ? InitContents::kUninit : InitContents::kClear;
1091 
1092     return Device::Make(std::move(sdc), cinfo.fInfo.alphaType(), init).release();
1093 }
1094 
makeSurface(const SkImageInfo & info,const SkSurfaceProps & props)1095 sk_sp<SkSurface> Device::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1096     ASSERT_SINGLE_OWNER
1097     // TODO: Change the signature of newSurface to take a budgeted parameter.
1098     static const SkBudgeted kBudgeted = SkBudgeted::kNo;
1099     return SkSurface::MakeRenderTarget(fContext.get(), kBudgeted, info,
1100                                        fSurfaceDrawContext->numSamples(),
1101                                        fSurfaceDrawContext->origin(), &props);
1102 }
1103 
getImageFilterCache()1104 SkImageFilterCache* Device::getImageFilterCache() {
1105     ASSERT_SINGLE_OWNER
1106     // We always return a transient cache, so it is freed after each
1107     // filter traversal.
1108     return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize);
1109 }
1110 
1111 ////////////////////////////////////////////////////////////////////////////////////
1112 
android_utils_clipWithStencil()1113 bool Device::android_utils_clipWithStencil() {
1114     SkRegion clipRegion;
1115     this->onAsRgnClip(&clipRegion);
1116     if (clipRegion.isEmpty()) {
1117         return false;
1118     }
1119     auto sdc = fSurfaceDrawContext.get();
1120     SkASSERT(sdc);
1121     GrPaint grPaint;
1122     grPaint.setXPFactory(GrDisableColorXPFactory::Get());
1123     static constexpr GrUserStencilSettings kDrawToStencil(
1124         GrUserStencilSettings::StaticInit<
1125             0x1,
1126             GrUserStencilTest::kAlways,
1127             0x1,
1128             GrUserStencilOp::kReplace,
1129             GrUserStencilOp::kReplace,
1130             0x1>()
1131     );
1132     // Regions don't actually need AA, but in DMSAA mode everything is antialiased.
1133     GrAA aa = GrAA(fSurfaceDrawContext->alwaysAntialias());
1134     sdc->drawRegion(nullptr, std::move(grPaint), aa, SkMatrix::I(), clipRegion,
1135                     GrStyle::SimpleFill(), &kDrawToStencil);
1136     return true;
1137 }
1138 
1139 } // namespace skgpu::v1
1140