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