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