• 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 "src/core/SkCanvasPriv.h"
22 #include "src/core/SkClipStack.h"
23 #include "src/core/SkDraw.h"
24 #include "src/core/SkImageFilterCache.h"
25 #include "src/core/SkImageFilter_Base.h"
26 #include "src/core/SkLatticeIter.h"
27 #include "src/core/SkPictureData.h"
28 #include "src/core/SkRRectPriv.h"
29 #include "src/core/SkRasterClip.h"
30 #include "src/core/SkRecord.h"
31 #include "src/core/SkStroke.h"
32 #include "src/core/SkTLazy.h"
33 #include "src/core/SkVerticesPriv.h"
34 #include "src/gpu/GrBlurUtils.h"
35 #include "src/gpu/GrDirectContextPriv.h"
36 #include "src/gpu/GrGpu.h"
37 #include "src/gpu/GrRecordingContextPriv.h"
38 #include "src/gpu/GrStyle.h"
39 #include "src/gpu/GrSurfaceProxyPriv.h"
40 #include "src/gpu/GrTracing.h"
41 #include "src/gpu/SkGr.h"
42 #include "src/gpu/effects/GrDisableColorXP.h"
43 #include "src/gpu/effects/GrRRectEffect.h"
44 #include "src/gpu/geometry/GrStyledShape.h"
45 #include "src/image/SkImage_Base.h"
46 #include "src/image/SkReadPixelsRec.h"
47 #include "src/image/SkSurface_Gpu.h"
48 #include "src/utils/SkUTF.h"
49 
50 #define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fContext->priv().singleOwner())
51 
52 
53 ///////////////////////////////////////////////////////////////////////////////
54 
55 namespace {
56 
force_aa_clip(const skgpu::v1::SurfaceDrawContext * sdc)57 bool force_aa_clip(const skgpu::v1::SurfaceDrawContext* sdc) {
58     return sdc->numSamples() > 1 || sdc->alwaysAntialias();
59 }
60 
point_mode_to_primitive_type(SkCanvas::PointMode mode)61 inline GrPrimitiveType point_mode_to_primitive_type(SkCanvas::PointMode mode) {
62     switch (mode) {
63         case SkCanvas::kPoints_PointMode:
64             return GrPrimitiveType::kPoints;
65         case SkCanvas::kLines_PointMode:
66             return GrPrimitiveType::kLines;
67         case SkCanvas::kPolygon_PointMode:
68             return GrPrimitiveType::kLineStrip;
69     }
70     SK_ABORT("Unexpected mode");
71 }
72 
make_inverse_rrect_fp(const SkMatrix & viewMatrix,const SkRRect & rrect,GrAA aa,const GrShaderCaps & shaderCaps)73 std::unique_ptr<GrFragmentProcessor> make_inverse_rrect_fp(const SkMatrix& viewMatrix,
74                                                            const SkRRect& rrect, GrAA aa,
75                                                            const GrShaderCaps& shaderCaps) {
76     SkTCopyOnFirstWrite<SkRRect> devRRect(rrect);
77     if (viewMatrix.isIdentity() || rrect.transform(viewMatrix, devRRect.writable())) {
78         auto edgeType = (aa == GrAA::kYes) ? GrClipEdgeType::kInverseFillAA
79                                            : GrClipEdgeType::kInverseFillBW;
80         auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr, edgeType, *devRRect,
81                                                  shaderCaps);
82         return (success) ? std::move(fp) : nullptr;
83     }
84     return nullptr;
85 }
86 
init_vertices_paint(GrRecordingContext * rContext,const GrColorInfo & colorInfo,const SkPaint & skPaint,const SkMatrixProvider & matrixProvider,SkBlendMode bmode,bool hasColors,GrPaint * grPaint)87 bool init_vertices_paint(GrRecordingContext* rContext,
88                          const GrColorInfo& colorInfo,
89                          const SkPaint& skPaint,
90                          const SkMatrixProvider& matrixProvider,
91                          SkBlendMode bmode,
92                          bool hasColors,
93                          GrPaint* grPaint) {
94     if (hasColors) {
95         // When there are colors and a shader, the shader and colors are combined using bmode.
96         // With no shader, we just use the colors (kDst).
97         return SkPaintToGrPaintWithBlend(rContext,
98                                          colorInfo,
99                                          skPaint,
100                                          matrixProvider,
101                                          skPaint.getShader() ? bmode : SkBlendMode::kDst,
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 (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
348         GrStyle style(paint, SkPaint::kStroke_Style);
349         GrPaint grPaint;
350         if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
351                               this->asMatrixProvider(), &grPaint)) {
352             return;
353         }
354         SkPath path;
355         path.setIsVolatile(true);
356         path.moveTo(pts[0]);
357         path.lineTo(pts[1]);
358         fSurfaceDrawContext->drawPath(this->clip(), std::move(grPaint), aa, this->localToDevice(),
359                                       path, style);
360         return;
361     }
362 
363     SkScalar scales[2];
364     bool isHairline = (0 == width) ||
365                        (1 == width && this->localToDevice().getMinMaxScales(scales) &&
366                         SkScalarNearlyEqual(scales[0], 1.f) && SkScalarNearlyEqual(scales[1], 1.f));
367     // we only handle non-coverage-aa hairlines and paints without path effects or mask filters,
368     // else we let the SkDraw call our drawPath()
369     if (!isHairline ||
370         paint.getPathEffect() ||
371         paint.getMaskFilter() ||
372         fSurfaceDrawContext->chooseAAType(aa) == GrAAType::kCoverage) {
373         SkRasterClip rc(this->devClipBounds());
374         SkDraw draw;
375         draw.fDst = SkPixmap(SkImageInfo::MakeUnknown(this->width(), this->height()), nullptr, 0);
376         draw.fMatrixProvider = this;
377         draw.fRC = &rc;
378         draw.drawPoints(mode, count, pts, paint, this);
379         return;
380     }
381 
382     GrPrimitiveType primitiveType = point_mode_to_primitive_type(mode);
383 
384     const SkMatrixProvider* matrixProvider = this;
385 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
386     SkTLazy<SkPostTranslateMatrixProvider> postTranslateMatrixProvider;
387     // This offsetting in device space matches the expectations of the Android framework for non-AA
388     // points and lines.
389     if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) {
390         static const SkScalar kOffset = 0.063f; // Just greater than 1/16.
391         matrixProvider = postTranslateMatrixProvider.init(*matrixProvider, kOffset, kOffset);
392     }
393 #endif
394 
395     GrPaint grPaint;
396     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
397                           *matrixProvider, &grPaint)) {
398         return;
399     }
400 
401     static constexpr SkVertices::VertexMode kIgnoredMode = SkVertices::kTriangles_VertexMode;
402     sk_sp<SkVertices> vertices = SkVertices::MakeCopy(kIgnoredMode, SkToS32(count), pts, nullptr,
403                                                       nullptr);
404 
405     fSurfaceDrawContext->drawVertices(this->clip(), std::move(grPaint), *matrixProvider,
406                                       std::move(vertices), &primitiveType);
407 }
408 
409 ///////////////////////////////////////////////////////////////////////////////
410 
drawRect(const SkRect & rect,const SkPaint & paint)411 void Device::drawRect(const SkRect& rect, const SkPaint& paint) {
412     ASSERT_SINGLE_OWNER
413     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawRect", fContext.get());
414 
415     GrStyle style(paint);
416 
417     // A couple reasons we might need to call drawPath.
418     if (paint.getMaskFilter() || paint.getPathEffect()) {
419         GrStyledShape shape(rect, style);
420 
421         GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(),
422                                              this->clip(), paint, this->asMatrixProvider(), shape);
423         return;
424     }
425 
426     GrPaint grPaint;
427     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
428                           this->asMatrixProvider(), &grPaint)) {
429         return;
430     }
431 
432     fSurfaceDrawContext->drawRect(this->clip(), std::move(grPaint),
433                                   fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), rect,
434                                   &style);
435 }
436 
drawEdgeAAQuad(const SkRect & rect,const SkPoint clip[4],SkCanvas::QuadAAFlags aaFlags,const SkColor4f & color,SkBlendMode mode)437 void Device::drawEdgeAAQuad(const SkRect& rect,
438                             const SkPoint clip[4],
439                             SkCanvas::QuadAAFlags aaFlags,
440                             const SkColor4f& color,
441                             SkBlendMode mode) {
442     ASSERT_SINGLE_OWNER
443     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawEdgeAAQuad", fContext.get());
444 
445     SkPMColor4f dstColor = SkColor4fPrepForDst(color, fSurfaceDrawContext->colorInfo()).premul();
446 
447     GrPaint grPaint;
448     grPaint.setColor4f(dstColor);
449     if (mode != SkBlendMode::kSrcOver) {
450         grPaint.setXPFactory(SkBlendMode_AsXPFactory(mode));
451     }
452 
453     // This is exclusively meant for tiling operations, so keep AA enabled to handle MSAA seaming
454     GrQuadAAFlags grAA = SkToGrQuadAAFlags(aaFlags);
455     if (clip) {
456         // Use fillQuadWithEdgeAA
457         fSurfaceDrawContext->fillQuadWithEdgeAA(this->clip(), std::move(grPaint), GrAA::kYes, grAA,
458                                                 this->localToDevice(), clip, nullptr);
459     } else {
460         // Use fillRectWithEdgeAA to preserve mathematical properties of dst being rectangular
461         fSurfaceDrawContext->fillRectWithEdgeAA(this->clip(), std::move(grPaint), GrAA::kYes, grAA,
462                                                 this->localToDevice(), rect);
463     }
464 }
465 
466 ///////////////////////////////////////////////////////////////////////////////
467 
drawRRect(const SkRRect & rrect,const SkPaint & paint)468 void Device::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
469     ASSERT_SINGLE_OWNER
470     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawRRect", fContext.get());
471 
472     SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter());
473     if (mf) {
474         if (mf->hasFragmentProcessor()) {
475             mf = nullptr; // already handled in SkPaintToGrPaint
476         }
477     }
478 
479     GrStyle style(paint);
480 
481     if (mf || style.pathEffect()) {
482         // A path effect will presumably transform this rrect into something else.
483         GrStyledShape shape(rrect, style);
484 
485         GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(),
486                                              this->clip(), paint, this->asMatrixProvider(), shape);
487         return;
488     }
489 
490     SkASSERT(!style.pathEffect());
491 
492     GrPaint grPaint;
493     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
494                           this->asMatrixProvider(), &grPaint)) {
495         return;
496     }
497 
498     fSurfaceDrawContext->drawRRect(this->clip(), std::move(grPaint),
499                                    fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
500                                    rrect, style);
501 }
502 
drawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)503 void Device::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
504     ASSERT_SINGLE_OWNER
505     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawDRRect", fContext.get());
506     if (outer.isEmpty()) {
507        return;
508     }
509 
510     if (inner.isEmpty()) {
511         return this->drawRRect(outer, paint);
512     }
513 
514     SkStrokeRec stroke(paint);
515 
516     if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) {
517         // For axis-aligned filled DRRects, just draw a regular rrect with inner clipped out using a
518         // coverage FP instead of using path rendering.
519         if (auto fp = make_inverse_rrect_fp(this->localToDevice(), inner,
520                                             fSurfaceDrawContext->chooseAA(paint),
521                                             *fSurfaceDrawContext->caps()->shaderCaps())) {
522             GrPaint grPaint;
523             if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
524                                   this->asMatrixProvider(), &grPaint)) {
525                 return;
526             }
527             SkASSERT(!grPaint.hasCoverageFragmentProcessor());
528             grPaint.setCoverageFragmentProcessor(std::move(fp));
529             fSurfaceDrawContext->drawRRect(this->clip(), std::move(grPaint),
530                                            fSurfaceDrawContext->chooseAA(paint),
531                                            this->localToDevice(), outer, GrStyle());
532             return;
533         }
534     }
535 
536     SkPath path;
537     path.setIsVolatile(true);
538     path.addRRect(outer);
539     path.addRRect(inner);
540     path.setFillType(SkPathFillType::kEvenOdd);
541 
542     // TODO: We are losing the possible mutability of the path here but this should probably be
543     // fixed by upgrading GrStyledShape to handle DRRects.
544     GrStyledShape shape(path, paint);
545 
546     GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), this->clip(),
547                                          paint, this->asMatrixProvider(), shape);
548 }
549 
550 /////////////////////////////////////////////////////////////////////////////
551 
drawRegion(const SkRegion & region,const SkPaint & paint)552 void Device::drawRegion(const SkRegion& region, const SkPaint& paint) {
553     ASSERT_SINGLE_OWNER
554 
555     if (paint.getMaskFilter()) {
556         SkPath path;
557         region.getBoundaryPath(&path);
558         path.setIsVolatile(true);
559         return this->drawPath(path, paint, true);
560     }
561 
562     GrPaint grPaint;
563     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
564                           this->asMatrixProvider(), &grPaint)) {
565         return;
566     }
567 
568     fSurfaceDrawContext->drawRegion(this->clip(), std::move(grPaint),
569                                     fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
570                                     region, GrStyle(paint));
571 }
572 
drawOval(const SkRect & oval,const SkPaint & paint)573 void Device::drawOval(const SkRect& oval, const SkPaint& paint) {
574     ASSERT_SINGLE_OWNER
575     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawOval", fContext.get());
576 
577     if (paint.getMaskFilter()) {
578         // The RRect path can handle special case blurring
579         SkRRect rr = SkRRect::MakeOval(oval);
580         return this->drawRRect(rr, paint);
581     }
582 
583     GrPaint grPaint;
584     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
585                           this->asMatrixProvider(), &grPaint)) {
586         return;
587     }
588 
589     fSurfaceDrawContext->drawOval(this->clip(), std::move(grPaint),
590                                   fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), oval,
591                                   GrStyle(paint));
592 }
593 
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)594 void Device::drawArc(const SkRect& oval,
595                      SkScalar startAngle,
596                      SkScalar sweepAngle,
597                      bool useCenter,
598                      const SkPaint& paint) {
599     ASSERT_SINGLE_OWNER
600     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawArc", fContext.get());
601     if (paint.getMaskFilter()) {
602         this->INHERITED::drawArc(oval, startAngle, sweepAngle, useCenter, paint);
603         return;
604     }
605     GrPaint grPaint;
606     if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
607                           this->asMatrixProvider(), &grPaint)) {
608         return;
609     }
610 
611     fSurfaceDrawContext->drawArc(this->clip(), std::move(grPaint),
612                                  fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), oval,
613                                  startAngle, sweepAngle, useCenter, GrStyle(paint));
614 }
615 
616 ///////////////////////////////////////////////////////////////////////////////
617 
drawPath(const SkPath & origSrcPath,const SkPaint & paint,bool pathIsMutable)618 void Device::drawPath(const SkPath& origSrcPath, const SkPaint& paint, bool pathIsMutable) {
619 #if GR_TEST_UTILS
620     if (fContext->priv().options().fAllPathsVolatile && !origSrcPath.isVolatile()) {
621         this->drawPath(SkPath(origSrcPath).setIsVolatile(true), paint, true);
622         return;
623     }
624 #endif
625     ASSERT_SINGLE_OWNER
626     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPath", fContext.get());
627     if (!paint.getMaskFilter()) {
628         GrPaint grPaint;
629         if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
630                               this->asMatrixProvider(), &grPaint)) {
631             return;
632         }
633         fSurfaceDrawContext->drawPath(this->clip(), std::move(grPaint),
634                                       fSurfaceDrawContext->chooseAA(paint), this->localToDevice(),
635                                       origSrcPath, GrStyle(paint));
636         return;
637     }
638 
639     // TODO: losing possible mutability of 'origSrcPath' here
640     GrStyledShape shape(origSrcPath, paint);
641 
642     GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), this->clip(),
643                                          paint, this->asMatrixProvider(), shape);
644 }
645 
makeSpecial(const SkBitmap & bitmap)646 sk_sp<SkSpecialImage> Device::makeSpecial(const SkBitmap& bitmap) {
647     ASSERT_SINGLE_OWNER
648 
649     // TODO: this makes a tight copy of 'bitmap' but it doesn't have to be (given SkSpecialImage's
650     // semantics). Since this is cached we would have to bake the fit into the cache key though.
651     auto view = std::get<0>(GrMakeCachedBitmapProxyView(fContext.get(), bitmap));
652     if (!view) {
653         return nullptr;
654     }
655 
656     const SkIRect rect = SkIRect::MakeSize(view.proxy()->dimensions());
657 
658     // GrMakeCachedBitmapProxyView creates a tight copy of 'bitmap' so we don't have to subset
659     // the special image
660     return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
661                                                rect,
662                                                bitmap.getGenerationID(),
663                                                std::move(view),
664                                                SkColorTypeToGrColorType(bitmap.colorType()),
665                                                bitmap.refColorSpace(),
666                                                this->surfaceProps());
667 }
668 
makeSpecial(const SkImage * image)669 sk_sp<SkSpecialImage> Device::makeSpecial(const SkImage* image) {
670     ASSERT_SINGLE_OWNER
671 
672     SkPixmap pm;
673     if (image->isTextureBacked()) {
674         auto [view, ct] = as_IB(image)->asView(this->recordingContext(), GrMipmapped::kNo);
675         SkASSERT(view);
676 
677         return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
678                                                    SkIRect::MakeWH(image->width(), image->height()),
679                                                    image->uniqueID(),
680                                                    std::move(view),
681                                                    ct,
682                                                    image->refColorSpace(),
683                                                    this->surfaceProps());
684     } else if (image->peekPixels(&pm)) {
685         SkBitmap bm;
686 
687         bm.installPixels(pm);
688         return this->makeSpecial(bm);
689     } else {
690         return nullptr;
691     }
692 }
693 
snapSpecial(const SkIRect & subset,bool forceCopy)694 sk_sp<SkSpecialImage> Device::snapSpecial(const SkIRect& subset, bool forceCopy) {
695     ASSERT_SINGLE_OWNER
696 
697     auto sdc = fSurfaceDrawContext.get();
698 
699     // If we are wrapping a vulkan secondary command buffer, then we can't snap off a special image
700     // since it would require us to make a copy of the underlying VkImage which we don't have access
701     // to. Additionaly we can't stop and start the render pass that is used with the secondary
702     // command buffer.
703     if (sdc->wrapsVkSecondaryCB()) {
704         return nullptr;
705     }
706 
707     SkASSERT(sdc->asSurfaceProxy());
708 
709     SkIRect finalSubset = subset;
710     GrSurfaceProxyView view = sdc->readSurfaceView();
711     if (forceCopy || !view.asTextureProxy()) {
712         // When the device doesn't have a texture, or a copy is requested, we create a temporary
713         // texture that matches the device contents
714         view = GrSurfaceProxyView::Copy(fContext.get(),
715                                         std::move(view),
716                                         GrMipmapped::kNo,  // Don't auto generate mips
717                                         subset,
718                                         SkBackingFit::kApprox,
719                                         SkBudgeted::kYes);  // Always budgeted
720         if (!view) {
721             return nullptr;
722         }
723         // Since this copied only the requested subset, the special image wrapping the proxy no
724         // longer needs the original subset.
725         finalSubset = SkIRect::MakeSize(view.dimensions());
726     }
727 
728     GrColorType ct = SkColorTypeToGrColorType(this->imageInfo().colorType());
729 
730     return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
731                                                finalSubset,
732                                                kNeedNewImageUniqueID_SpecialImage,
733                                                std::move(view),
734                                                ct,
735                                                this->imageInfo().refColorSpace(),
736                                                this->surfaceProps());
737 }
738 
drawDevice(SkBaseDevice * device,const SkSamplingOptions & sampling,const SkPaint & paint)739 void Device::drawDevice(SkBaseDevice* device,
740                         const SkSamplingOptions& sampling,
741                         const SkPaint& paint) {
742     ASSERT_SINGLE_OWNER
743     // clear of the source device must occur before CHECK_SHOULD_DRAW
744     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawDevice", fContext.get());
745     this->INHERITED::drawDevice(device, sampling, paint);
746 }
747 
drawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint & paint,SkCanvas::SrcRectConstraint constraint)748 void Device::drawImageRect(const SkImage* image,
749                            const SkRect* src,
750                            const SkRect& dst,
751                            const SkSamplingOptions& sampling,
752                            const SkPaint& paint,
753                            SkCanvas::SrcRectConstraint constraint) {
754     ASSERT_SINGLE_OWNER
755     GrAA aa = fSurfaceDrawContext->chooseAA(paint);
756     GrQuadAAFlags aaFlags = (aa == GrAA::kYes) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
757     this->drawImageQuad(image, src, &dst, nullptr, aa, aaFlags, nullptr, sampling, paint,
758                         constraint);
759 }
760 
drawViewLattice(GrSurfaceProxyView view,const GrColorInfo & info,std::unique_ptr<SkLatticeIter> iter,const SkRect & dst,SkFilterMode filter,const SkPaint & origPaint)761 void Device::drawViewLattice(GrSurfaceProxyView view,
762                              const GrColorInfo& info,
763                              std::unique_ptr<SkLatticeIter> iter,
764                              const SkRect& dst,
765                              SkFilterMode filter,
766                              const SkPaint& origPaint) {
767     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawViewLattice", fContext.get());
768     SkASSERT(view);
769 
770     SkTCopyOnFirstWrite<SkPaint> paint(&origPaint);
771 
772     if (!info.isAlphaOnly() && (paint->getColor() & 0x00FFFFFF) != 0x00FFFFFF) {
773         paint.writable()->setColor(SkColorSetARGB(origPaint.getAlpha(), 0xFF, 0xFF, 0xFF));
774     }
775     GrPaint grPaint;
776     if (!SkPaintToGrPaintWithPrimitiveColor(this->recordingContext(),
777                                             fSurfaceDrawContext->colorInfo(), *paint,
778                                             this->asMatrixProvider(), &grPaint)) {
779         return;
780     }
781 
782     if (info.isAlphaOnly()) {
783         // If we were doing this with an FP graph we'd use a kDstIn blend between the texture and
784         // the paint color.
785         view.concatSwizzle(GrSwizzle("aaaa"));
786     }
787     auto csxf = GrColorSpaceXform::Make(info, fSurfaceDrawContext->colorInfo());
788 
789     fSurfaceDrawContext->drawImageLattice(this->clip(), std::move(grPaint), this->localToDevice(),
790                                           std::move(view), info.alphaType(), std::move(csxf),
791                                           filter, std::move(iter), dst);
792 }
793 
drawImageLattice(const SkImage * image,const SkCanvas::Lattice & lattice,const SkRect & dst,SkFilterMode filter,const SkPaint & paint)794 void Device::drawImageLattice(const SkImage* image,
795                               const SkCanvas::Lattice& lattice,
796                               const SkRect& dst,
797                               SkFilterMode filter,
798                               const SkPaint& paint) {
799     ASSERT_SINGLE_OWNER
800     auto iter = std::make_unique<SkLatticeIter>(lattice, dst);
801     if (auto [view, ct] = as_IB(image)->asView(this->recordingContext(), GrMipmapped::kNo); view) {
802         GrColorInfo colorInfo(ct, image->alphaType(), image->refColorSpace());
803         this->drawViewLattice(std::move(view),
804                               std::move(colorInfo),
805                               std::move(iter),
806                               dst,
807                               filter,
808                               paint);
809     }
810 }
811 
drawVertices(const SkVertices * vertices,SkBlendMode mode,const SkPaint & paint)812 void Device::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
813     ASSERT_SINGLE_OWNER
814     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawVertices", fContext.get());
815     SkASSERT(vertices);
816 
817     SkVerticesPriv info(vertices->priv());
818 
819     GrPaint grPaint;
820     if (!init_vertices_paint(fContext.get(), fSurfaceDrawContext->colorInfo(), paint,
821                              this->asMatrixProvider(), mode, info.hasColors(), &grPaint)) {
822         return;
823     }
824     fSurfaceDrawContext->drawVertices(this->clip(),
825                                       std::move(grPaint),
826                                       this->asMatrixProvider(),
827                                       sk_ref_sp(const_cast<SkVertices*>(vertices)),
828                                       nullptr);
829 }
830 
831 ///////////////////////////////////////////////////////////////////////////////
832 
drawShadow(const SkPath & path,const SkDrawShadowRec & rec)833 void Device::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
834 #if GR_TEST_UTILS
835     if (fContext->priv().options().fAllPathsVolatile && !path.isVolatile()) {
836         this->drawShadow(SkPath(path).setIsVolatile(true), rec);
837         return;
838     }
839 #endif
840     ASSERT_SINGLE_OWNER
841     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawShadow", fContext.get());
842 
843     if (!fSurfaceDrawContext->drawFastShadow(this->clip(), this->localToDevice(), path, rec)) {
844         // failed to find an accelerated case
845         this->INHERITED::drawShadow(path, rec);
846     }
847 }
848 
849 ///////////////////////////////////////////////////////////////////////////////
850 
drawAtlas(const SkRSXform xform[],const SkRect texRect[],const SkColor colors[],int count,SkBlendMode mode,const SkPaint & paint)851 void Device::drawAtlas(const SkRSXform xform[],
852                        const SkRect texRect[],
853                        const SkColor colors[],
854                        int count,
855                        SkBlendMode mode,
856                        const SkPaint& paint) {
857     ASSERT_SINGLE_OWNER
858     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawAtlas", fContext.get());
859 
860     GrPaint grPaint;
861     if (colors) {
862         if (!SkPaintToGrPaintWithBlend(this->recordingContext(), fSurfaceDrawContext->colorInfo(),
863                                        paint, this->asMatrixProvider(), mode, &grPaint)) {
864             return;
865         }
866     } else {
867         if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(),
868                               paint, this->asMatrixProvider(), &grPaint)) {
869             return;
870         }
871     }
872 
873     fSurfaceDrawContext->drawAtlas(this->clip(), std::move(grPaint), this->localToDevice(), count,
874                                    xform, texRect, colors);
875 }
876 
877 ///////////////////////////////////////////////////////////////////////////////
878 
onDrawGlyphRunList(const SkGlyphRunList & glyphRunList,const SkPaint & paint)879 void Device::onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint) {
880     ASSERT_SINGLE_OWNER
881     GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawGlyphRunList", fContext.get());
882     SkASSERT(!glyphRunList.hasRSXForm());
883 
884     fSurfaceDrawContext->drawGlyphRunList(
885         this->clip(), this->asMatrixProvider(), glyphRunList, paint);
886 }
887 
888 ///////////////////////////////////////////////////////////////////////////////
889 
drawDrawable(SkDrawable * drawable,const SkMatrix * matrix,SkCanvas * canvas)890 void Device::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix, SkCanvas* canvas) {
891     ASSERT_SINGLE_OWNER
892 
893     GrBackendApi api = this->recordingContext()->backend();
894     if (GrBackendApi::kVulkan == api) {
895         const SkMatrix& ctm = this->localToDevice();
896         const SkMatrix& combinedMatrix = matrix ? SkMatrix::Concat(ctm, *matrix) : ctm;
897         std::unique_ptr<SkDrawable::GpuDrawHandler> gpuDraw =
898                 drawable->snapGpuDrawHandler(api, combinedMatrix, this->devClipBounds(),
899                                              this->imageInfo());
900         if (gpuDraw) {
901             fSurfaceDrawContext->drawDrawable(
902                     std::move(gpuDraw), combinedMatrix.mapRect(drawable->getBounds()));
903             return;
904         }
905     }
906     this->INHERITED::drawDrawable(drawable, matrix, canvas);
907 }
908 
909 
910 ///////////////////////////////////////////////////////////////////////////////
911 
wait(int numSemaphores,const GrBackendSemaphore * waitSemaphores,bool deleteSemaphoresAfterWait)912 bool Device::wait(int numSemaphores,
913                   const GrBackendSemaphore* waitSemaphores,
914                   bool deleteSemaphoresAfterWait) {
915     ASSERT_SINGLE_OWNER
916 
917     return fSurfaceDrawContext->waitOnSemaphores(numSemaphores, waitSemaphores,
918                                                  deleteSemaphoresAfterWait);
919 }
920 
replaceBackingProxy(SkSurface::ContentChangeMode mode,sk_sp<GrRenderTargetProxy> newRTP,GrColorType grColorType,sk_sp<SkColorSpace> colorSpace,GrSurfaceOrigin origin,const SkSurfaceProps & props)921 bool Device::replaceBackingProxy(SkSurface::ContentChangeMode mode,
922                                  sk_sp<GrRenderTargetProxy> newRTP,
923                                  GrColorType grColorType,
924                                  sk_sp<SkColorSpace> colorSpace,
925                                  GrSurfaceOrigin origin,
926                                  const SkSurfaceProps& props) {
927     auto sdc = SurfaceDrawContext::Make(fContext.get(), grColorType, std::move(newRTP),
928                                         std::move(colorSpace), origin, props);
929     if (!sdc) {
930         return false;
931     }
932 
933     SkASSERT(sdc->dimensions() == fSurfaceDrawContext->dimensions());
934     SkASSERT(sdc->numSamples() == fSurfaceDrawContext->numSamples());
935     SkASSERT(sdc->asSurfaceProxy()->priv().isExact());
936     if (mode == SkSurface::kRetain_ContentChangeMode) {
937         if (fContext->abandoned()) {
938             return false;
939         }
940 
941         SkASSERT(fSurfaceDrawContext->asTextureProxy());
942         SkAssertResult(sdc->blitTexture(fSurfaceDrawContext->readSurfaceView(),
943                                         SkIRect::MakeWH(this->width(), this->height()),
944                                         SkIPoint::Make(0, 0)));
945     }
946 
947     fSurfaceDrawContext = std::move(sdc);
948     return true;
949 }
950 
asyncRescaleAndReadPixels(const SkImageInfo & info,const SkIRect & srcRect,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)951 void Device::asyncRescaleAndReadPixels(const SkImageInfo& info,
952                                        const SkIRect& srcRect,
953                                        RescaleGamma rescaleGamma,
954                                        RescaleMode rescaleMode,
955                                        ReadPixelsCallback callback,
956                                        ReadPixelsContext context) {
957     auto* sdc = fSurfaceDrawContext.get();
958     // Context TODO: Elevate direct context requirement to public API.
959     auto dContext = sdc->recordingContext()->asDirectContext();
960     if (!dContext) {
961         return;
962     }
963     sdc->asyncRescaleAndReadPixels(dContext, info, srcRect, rescaleGamma, rescaleMode, callback,
964                                    context);
965 }
966 
asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,SkISize dstSize,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)967 void Device::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
968                                              sk_sp<SkColorSpace> dstColorSpace,
969                                              const SkIRect& srcRect,
970                                              SkISize dstSize,
971                                              RescaleGamma rescaleGamma,
972                                              RescaleMode rescaleMode,
973                                              ReadPixelsCallback callback,
974                                              ReadPixelsContext context) {
975     auto* sdc = fSurfaceDrawContext.get();
976     // Context TODO: Elevate direct context requirement to public API.
977     auto dContext = sdc->recordingContext()->asDirectContext();
978     if (!dContext) {
979         return;
980     }
981     sdc->asyncRescaleAndReadPixelsYUV420(dContext,
982                                          yuvColorSpace,
983                                          std::move(dstColorSpace),
984                                          srcRect,
985                                          dstSize,
986                                          rescaleGamma,
987                                          rescaleMode,
988                                          callback,
989                                          context);
990 }
991 
992 ///////////////////////////////////////////////////////////////////////////////
993 
onCreateDevice(const CreateInfo & cinfo,const SkPaint *)994 SkBaseDevice* Device::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
995     ASSERT_SINGLE_OWNER
996 
997     SkSurfaceProps props(this->surfaceProps().flags(), cinfo.fPixelGeometry);
998 
999     // layers are never drawn in repeat modes, so we can request an approx
1000     // match and ignore any padding.
1001     SkBackingFit fit = kNever_TileUsage == cinfo.fTileUsage ? SkBackingFit::kApprox
1002                                                             : SkBackingFit::kExact;
1003 
1004     SkASSERT(cinfo.fInfo.colorType() != kRGBA_1010102_SkColorType);
1005 
1006     auto sdc = SurfaceDrawContext::MakeWithFallback(
1007             fContext.get(), SkColorTypeToGrColorType(cinfo.fInfo.colorType()),
1008             fSurfaceDrawContext->colorInfo().refColorSpace(), fit, cinfo.fInfo.dimensions(), props,
1009             fSurfaceDrawContext->numSamples(), GrMipmapped::kNo,
1010             fSurfaceDrawContext->asSurfaceProxy()->isProtected(), kBottomLeft_GrSurfaceOrigin,
1011             SkBudgeted::kYes);
1012     if (!sdc) {
1013         return nullptr;
1014     }
1015 
1016     // Skia's convention is to only clear a device if it is non-opaque.
1017     InitContents init = cinfo.fInfo.isOpaque() ? InitContents::kUninit : InitContents::kClear;
1018 
1019     return Device::Make(std::move(sdc), cinfo.fInfo.alphaType(), init).release();
1020 }
1021 
makeSurface(const SkImageInfo & info,const SkSurfaceProps & props)1022 sk_sp<SkSurface> Device::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1023     ASSERT_SINGLE_OWNER
1024     // TODO: Change the signature of newSurface to take a budgeted parameter.
1025     static const SkBudgeted kBudgeted = SkBudgeted::kNo;
1026     return SkSurface::MakeRenderTarget(fContext.get(), kBudgeted, info,
1027                                        fSurfaceDrawContext->numSamples(),
1028                                        fSurfaceDrawContext->origin(), &props);
1029 }
1030 
getImageFilterCache()1031 SkImageFilterCache* Device::getImageFilterCache() {
1032     ASSERT_SINGLE_OWNER
1033     // We always return a transient cache, so it is freed after each
1034     // filter traversal.
1035     return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize);
1036 }
1037 
1038 ////////////////////////////////////////////////////////////////////////////////////
1039 
android_utils_clipWithStencil()1040 bool Device::android_utils_clipWithStencil() {
1041     SkRegion clipRegion;
1042     this->onAsRgnClip(&clipRegion);
1043     if (clipRegion.isEmpty()) {
1044         return false;
1045     }
1046     auto sdc = fSurfaceDrawContext.get();
1047     SkASSERT(sdc);
1048     GrPaint grPaint;
1049     grPaint.setXPFactory(GrDisableColorXPFactory::Get());
1050     static constexpr GrUserStencilSettings kDrawToStencil(
1051         GrUserStencilSettings::StaticInit<
1052             0x1,
1053             GrUserStencilTest::kAlways,
1054             0x1,
1055             GrUserStencilOp::kReplace,
1056             GrUserStencilOp::kReplace,
1057             0x1>()
1058     );
1059     // Regions don't actually need AA, but in DMSAA mode everything is antialiased.
1060     GrAA aa = GrAA(fSurfaceDrawContext->alwaysAntialias());
1061     sdc->drawRegion(nullptr, std::move(grPaint), aa, SkMatrix::I(), clipRegion,
1062                     GrStyle::SimpleFill(), &kDrawToStencil);
1063     return true;
1064 }
1065 
drawBlurImage(const SkImage * image,const SkBlurArg & blurArg)1066 bool Device::drawBlurImage(const SkImage* image, const SkBlurArg& blurArg)
1067 {
1068     if (image == nullptr) {
1069         return false;
1070     }
1071     if (auto[view, ct] = as_IB(image)->asView(this->recordingContext(), GrMipmapped::kNo); view) {
1072         return fSurfaceDrawContext->drawBlurImage(std::move(view), blurArg);
1073     }
1074 }
1075 
1076 } // namespace skgpu::v1
1077