xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrSurfaceProxy.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 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 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxy.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkBackingFit.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Swizzle.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuResourcePriv.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrImageInfo.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTargetProxy.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTask.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxyPriv.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxyView.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTextureProxy.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceContext.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceFillContext.h"
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
35*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
37*c8dee2aaSAndroid Build Coastguard Worker 
is_valid_lazy(const SkISize & dimensions,SkBackingFit fit)38*c8dee2aaSAndroid Build Coastguard Worker static bool is_valid_lazy(const SkISize& dimensions, SkBackingFit fit) {
39*c8dee2aaSAndroid Build Coastguard Worker     // A "fully" lazy proxy's width and height are not known until instantiation time.
40*c8dee2aaSAndroid Build Coastguard Worker     // So fully lazy proxies are created with width and height < 0. Regular lazy proxies must be
41*c8dee2aaSAndroid Build Coastguard Worker     // created with positive widths and heights. The width and height are set to 0 only after a
42*c8dee2aaSAndroid Build Coastguard Worker     // failed instantiation. The former must be "approximate" fit while the latter can be either.
43*c8dee2aaSAndroid Build Coastguard Worker     return ((dimensions.fWidth < 0 && dimensions.fHeight < 0 && SkBackingFit::kApprox == fit) ||
44*c8dee2aaSAndroid Build Coastguard Worker             (dimensions.fWidth > 0 && dimensions.fHeight > 0));
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker 
is_valid_non_lazy(SkISize dimensions)47*c8dee2aaSAndroid Build Coastguard Worker static bool is_valid_non_lazy(SkISize dimensions) {
48*c8dee2aaSAndroid Build Coastguard Worker     return dimensions.fWidth > 0 && dimensions.fHeight > 0;
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker #endif
51*c8dee2aaSAndroid Build Coastguard Worker 
LazyCallbackResult(sk_sp<GrSurface> surf,bool releaseCallback,LazyInstantiationKeyMode mode)52*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxy::LazyCallbackResult::LazyCallbackResult(sk_sp<GrSurface> surf,
53*c8dee2aaSAndroid Build Coastguard Worker                                                        bool releaseCallback,
54*c8dee2aaSAndroid Build Coastguard Worker                                                        LazyInstantiationKeyMode mode)
55*c8dee2aaSAndroid Build Coastguard Worker         : fSurface(std::move(surf)), fKeyMode(mode), fReleaseCallback(releaseCallback) {}
LazyCallbackResult(sk_sp<GrTexture> tex)56*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxy::LazyCallbackResult::LazyCallbackResult(sk_sp<GrTexture> tex)
57*c8dee2aaSAndroid Build Coastguard Worker         : LazyCallbackResult(sk_sp<GrSurface>(std::move(tex))) {}
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker // Deferred version
GrSurfaceProxy(const GrBackendFormat & format,SkISize dimensions,SkBackingFit fit,skgpu::Budgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,UseAllocator useAllocator,std::string_view label)60*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxy::GrSurfaceProxy(const GrBackendFormat& format,
61*c8dee2aaSAndroid Build Coastguard Worker                                SkISize dimensions,
62*c8dee2aaSAndroid Build Coastguard Worker                                SkBackingFit fit,
63*c8dee2aaSAndroid Build Coastguard Worker                                skgpu::Budgeted budgeted,
64*c8dee2aaSAndroid Build Coastguard Worker                                GrProtected isProtected,
65*c8dee2aaSAndroid Build Coastguard Worker                                GrInternalSurfaceFlags surfaceFlags,
66*c8dee2aaSAndroid Build Coastguard Worker                                UseAllocator useAllocator,
67*c8dee2aaSAndroid Build Coastguard Worker                                std::string_view label)
68*c8dee2aaSAndroid Build Coastguard Worker         : fSurfaceFlags(surfaceFlags)
69*c8dee2aaSAndroid Build Coastguard Worker         , fFormat(format)
70*c8dee2aaSAndroid Build Coastguard Worker         , fDimensions(dimensions)
71*c8dee2aaSAndroid Build Coastguard Worker         , fFit(fit)
72*c8dee2aaSAndroid Build Coastguard Worker         , fBudgeted(budgeted)
73*c8dee2aaSAndroid Build Coastguard Worker         , fUseAllocator(useAllocator)
74*c8dee2aaSAndroid Build Coastguard Worker         , fIsProtected(isProtected)
75*c8dee2aaSAndroid Build Coastguard Worker         , fLabel(label) {
76*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fFormat.isValid());
77*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(is_valid_non_lazy(dimensions));
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker // Lazy-callback version
GrSurfaceProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,SkISize dimensions,SkBackingFit fit,skgpu::Budgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,UseAllocator useAllocator,std::string_view label)81*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback,
82*c8dee2aaSAndroid Build Coastguard Worker                                const GrBackendFormat& format,
83*c8dee2aaSAndroid Build Coastguard Worker                                SkISize dimensions,
84*c8dee2aaSAndroid Build Coastguard Worker                                SkBackingFit fit,
85*c8dee2aaSAndroid Build Coastguard Worker                                skgpu::Budgeted budgeted,
86*c8dee2aaSAndroid Build Coastguard Worker                                GrProtected isProtected,
87*c8dee2aaSAndroid Build Coastguard Worker                                GrInternalSurfaceFlags surfaceFlags,
88*c8dee2aaSAndroid Build Coastguard Worker                                UseAllocator useAllocator,
89*c8dee2aaSAndroid Build Coastguard Worker                                std::string_view label)
90*c8dee2aaSAndroid Build Coastguard Worker         : fSurfaceFlags(surfaceFlags)
91*c8dee2aaSAndroid Build Coastguard Worker         , fFormat(format)
92*c8dee2aaSAndroid Build Coastguard Worker         , fDimensions(dimensions)
93*c8dee2aaSAndroid Build Coastguard Worker         , fFit(fit)
94*c8dee2aaSAndroid Build Coastguard Worker         , fBudgeted(budgeted)
95*c8dee2aaSAndroid Build Coastguard Worker         , fUseAllocator(useAllocator)
96*c8dee2aaSAndroid Build Coastguard Worker         , fLazyInstantiateCallback(std::move(callback))
97*c8dee2aaSAndroid Build Coastguard Worker         , fIsProtected(isProtected)
98*c8dee2aaSAndroid Build Coastguard Worker         , fLabel(label) {
99*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fFormat.isValid());
100*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fLazyInstantiateCallback);
101*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(is_valid_lazy(dimensions, fit));
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker 
104*c8dee2aaSAndroid Build Coastguard Worker // Wrapped version
GrSurfaceProxy(sk_sp<GrSurface> surface,SkBackingFit fit,UseAllocator useAllocator)105*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface,
106*c8dee2aaSAndroid Build Coastguard Worker                                SkBackingFit fit,
107*c8dee2aaSAndroid Build Coastguard Worker                                UseAllocator useAllocator)
108*c8dee2aaSAndroid Build Coastguard Worker         : fTarget(std::move(surface))
109*c8dee2aaSAndroid Build Coastguard Worker         , fSurfaceFlags(fTarget->flags())
110*c8dee2aaSAndroid Build Coastguard Worker         , fFormat(fTarget->backendFormat())
111*c8dee2aaSAndroid Build Coastguard Worker         , fDimensions(fTarget->dimensions())
112*c8dee2aaSAndroid Build Coastguard Worker         , fFit(fit)
113*c8dee2aaSAndroid Build Coastguard Worker         , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
114*c8dee2aaSAndroid Build Coastguard Worker                             ? skgpu::Budgeted::kYes
115*c8dee2aaSAndroid Build Coastguard Worker                             : skgpu::Budgeted::kNo)
116*c8dee2aaSAndroid Build Coastguard Worker         , fUseAllocator(useAllocator)
117*c8dee2aaSAndroid Build Coastguard Worker         , fUniqueID(fTarget->uniqueID())  // Note: converting from unique resource ID to a proxy ID!
118*c8dee2aaSAndroid Build Coastguard Worker         , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo)
119*c8dee2aaSAndroid Build Coastguard Worker         , fLabel(fTarget->getLabel()) {
120*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fFormat.isValid());
121*c8dee2aaSAndroid Build Coastguard Worker }
122*c8dee2aaSAndroid Build Coastguard Worker 
~GrSurfaceProxy()123*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxy::~GrSurfaceProxy() {
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker 
createSurfaceImpl(GrResourceProvider * resourceProvider,int sampleCnt,GrRenderable renderable,skgpu::Mipmapped mipmapped) const126*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
127*c8dee2aaSAndroid Build Coastguard Worker                                                    int sampleCnt,
128*c8dee2aaSAndroid Build Coastguard Worker                                                    GrRenderable renderable,
129*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Mipmapped mipmapped) const {
130*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipmapped == skgpu::Mipmapped::kNo || fFit == SkBackingFit::kExact);
131*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isLazy());
132*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fTarget);
133*c8dee2aaSAndroid Build Coastguard Worker 
134*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrSurface> surface;
135*c8dee2aaSAndroid Build Coastguard Worker     if (SkBackingFit::kApprox == fFit) {
136*c8dee2aaSAndroid Build Coastguard Worker         surface = resourceProvider->createApproxTexture(fDimensions,
137*c8dee2aaSAndroid Build Coastguard Worker                                                         fFormat,
138*c8dee2aaSAndroid Build Coastguard Worker                                                         fFormat.textureType(),
139*c8dee2aaSAndroid Build Coastguard Worker                                                         renderable,
140*c8dee2aaSAndroid Build Coastguard Worker                                                         sampleCnt,
141*c8dee2aaSAndroid Build Coastguard Worker                                                         fIsProtected,
142*c8dee2aaSAndroid Build Coastguard Worker                                                         fLabel);
143*c8dee2aaSAndroid Build Coastguard Worker     } else {
144*c8dee2aaSAndroid Build Coastguard Worker         surface = resourceProvider->createTexture(fDimensions,
145*c8dee2aaSAndroid Build Coastguard Worker                                                   fFormat,
146*c8dee2aaSAndroid Build Coastguard Worker                                                   fFormat.textureType(),
147*c8dee2aaSAndroid Build Coastguard Worker                                                   renderable,
148*c8dee2aaSAndroid Build Coastguard Worker                                                   sampleCnt,
149*c8dee2aaSAndroid Build Coastguard Worker                                                   mipmapped,
150*c8dee2aaSAndroid Build Coastguard Worker                                                   fBudgeted,
151*c8dee2aaSAndroid Build Coastguard Worker                                                   fIsProtected,
152*c8dee2aaSAndroid Build Coastguard Worker                                                   fLabel);
153*c8dee2aaSAndroid Build Coastguard Worker     }
154*c8dee2aaSAndroid Build Coastguard Worker     if (!surface) {
155*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
156*c8dee2aaSAndroid Build Coastguard Worker     }
157*c8dee2aaSAndroid Build Coastguard Worker 
158*c8dee2aaSAndroid Build Coastguard Worker     return surface;
159*c8dee2aaSAndroid Build Coastguard Worker }
160*c8dee2aaSAndroid Build Coastguard Worker 
canSkipResourceAllocator() const161*c8dee2aaSAndroid Build Coastguard Worker bool GrSurfaceProxy::canSkipResourceAllocator() const {
162*c8dee2aaSAndroid Build Coastguard Worker     if (fUseAllocator == UseAllocator::kNo) {
163*c8dee2aaSAndroid Build Coastguard Worker         // Usually an atlas or onFlush proxy
164*c8dee2aaSAndroid Build Coastguard Worker         return true;
165*c8dee2aaSAndroid Build Coastguard Worker     }
166*c8dee2aaSAndroid Build Coastguard Worker 
167*c8dee2aaSAndroid Build Coastguard Worker     auto peek = this->peekSurface();
168*c8dee2aaSAndroid Build Coastguard Worker     if (!peek) {
169*c8dee2aaSAndroid Build Coastguard Worker         return false;
170*c8dee2aaSAndroid Build Coastguard Worker     }
171*c8dee2aaSAndroid Build Coastguard Worker     // If this resource is already allocated and not recyclable then the resource allocator does
172*c8dee2aaSAndroid Build Coastguard Worker     // not need to do anything with it.
173*c8dee2aaSAndroid Build Coastguard Worker     return !peek->resourcePriv().getScratchKey().isValid();
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker 
assign(sk_sp<GrSurface> surface)176*c8dee2aaSAndroid Build Coastguard Worker void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
177*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fTarget && surface);
178*c8dee2aaSAndroid Build Coastguard Worker 
179*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(this->validateSurface(surface.get());)
180*c8dee2aaSAndroid Build Coastguard Worker 
181*c8dee2aaSAndroid Build Coastguard Worker     fTarget = std::move(surface);
182*c8dee2aaSAndroid Build Coastguard Worker 
183*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
184*c8dee2aaSAndroid Build Coastguard Worker     if (this->asRenderTargetProxy()) {
185*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fTarget->asRenderTarget());
186*c8dee2aaSAndroid Build Coastguard Worker     }
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker     // In order to give DDL users some flexibility in the destination of there DDLs,
189*c8dee2aaSAndroid Build Coastguard Worker     // a DDL's target proxy can be more conservative (and thus require less memory)
190*c8dee2aaSAndroid Build Coastguard Worker     // than the actual GrSurface used to fulfill it.
191*c8dee2aaSAndroid Build Coastguard Worker     if (!this->isDDLTarget() && kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
192*c8dee2aaSAndroid Build Coastguard Worker         // TODO(11373): Can this check be exact?
193*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
194*c8dee2aaSAndroid Build Coastguard Worker     }
195*c8dee2aaSAndroid Build Coastguard Worker #endif
196*c8dee2aaSAndroid Build Coastguard Worker }
197*c8dee2aaSAndroid Build Coastguard Worker 
instantiateImpl(GrResourceProvider * resourceProvider,int sampleCnt,GrRenderable renderable,skgpu::Mipmapped mipmapped,const skgpu::UniqueKey * uniqueKey)198*c8dee2aaSAndroid Build Coastguard Worker bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider,
199*c8dee2aaSAndroid Build Coastguard Worker                                      int sampleCnt,
200*c8dee2aaSAndroid Build Coastguard Worker                                      GrRenderable renderable,
201*c8dee2aaSAndroid Build Coastguard Worker                                      skgpu::Mipmapped mipmapped,
202*c8dee2aaSAndroid Build Coastguard Worker                                      const skgpu::UniqueKey* uniqueKey) {
203*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isLazy());
204*c8dee2aaSAndroid Build Coastguard Worker     if (fTarget) {
205*c8dee2aaSAndroid Build Coastguard Worker         if (uniqueKey && uniqueKey->isValid()) {
206*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
207*c8dee2aaSAndroid Build Coastguard Worker         }
208*c8dee2aaSAndroid Build Coastguard Worker         return true;
209*c8dee2aaSAndroid Build Coastguard Worker     }
210*c8dee2aaSAndroid Build Coastguard Worker 
211*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, renderable,
212*c8dee2aaSAndroid Build Coastguard Worker                                                        mipmapped);
213*c8dee2aaSAndroid Build Coastguard Worker     if (!surface) {
214*c8dee2aaSAndroid Build Coastguard Worker         return false;
215*c8dee2aaSAndroid Build Coastguard Worker     }
216*c8dee2aaSAndroid Build Coastguard Worker 
217*c8dee2aaSAndroid Build Coastguard Worker     // If there was an invalidation message pending for this key, we might have just processed it,
218*c8dee2aaSAndroid Build Coastguard Worker     // causing the key (stored on this proxy) to become invalid.
219*c8dee2aaSAndroid Build Coastguard Worker     if (uniqueKey && uniqueKey->isValid()) {
220*c8dee2aaSAndroid Build Coastguard Worker         resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
221*c8dee2aaSAndroid Build Coastguard Worker     }
222*c8dee2aaSAndroid Build Coastguard Worker 
223*c8dee2aaSAndroid Build Coastguard Worker     this->assign(std::move(surface));
224*c8dee2aaSAndroid Build Coastguard Worker 
225*c8dee2aaSAndroid Build Coastguard Worker     return true;
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker 
deinstantiate()228*c8dee2aaSAndroid Build Coastguard Worker void GrSurfaceProxy::deinstantiate() {
229*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->isInstantiated());
230*c8dee2aaSAndroid Build Coastguard Worker     fTarget = nullptr;
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker 
computeScratchKey(const GrCaps & caps,skgpu::ScratchKey * key) const233*c8dee2aaSAndroid Build Coastguard Worker void GrSurfaceProxy::computeScratchKey(const GrCaps& caps, skgpu::ScratchKey* key) const {
234*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isFullyLazy());
235*c8dee2aaSAndroid Build Coastguard Worker     GrRenderable renderable = GrRenderable::kNo;
236*c8dee2aaSAndroid Build Coastguard Worker     int sampleCount = 1;
237*c8dee2aaSAndroid Build Coastguard Worker     if (const auto* rtp = this->asRenderTargetProxy()) {
238*c8dee2aaSAndroid Build Coastguard Worker         renderable = GrRenderable::kYes;
239*c8dee2aaSAndroid Build Coastguard Worker         sampleCount = rtp->numSamples();
240*c8dee2aaSAndroid Build Coastguard Worker     }
241*c8dee2aaSAndroid Build Coastguard Worker 
242*c8dee2aaSAndroid Build Coastguard Worker     const GrTextureProxy* tp = this->asTextureProxy();
243*c8dee2aaSAndroid Build Coastguard Worker     skgpu::Mipmapped mipmapped = skgpu::Mipmapped::kNo;
244*c8dee2aaSAndroid Build Coastguard Worker     if (tp) {
245*c8dee2aaSAndroid Build Coastguard Worker         mipmapped = tp->mipmapped();
246*c8dee2aaSAndroid Build Coastguard Worker     }
247*c8dee2aaSAndroid Build Coastguard Worker 
248*c8dee2aaSAndroid Build Coastguard Worker     GrTexture::ComputeScratchKey(caps, this->backendFormat(), this->backingStoreDimensions(),
249*c8dee2aaSAndroid Build Coastguard Worker                                  renderable, sampleCount, mipmapped, fIsProtected, key);
250*c8dee2aaSAndroid Build Coastguard Worker }
251*c8dee2aaSAndroid Build Coastguard Worker 
backingStoreDimensions() const252*c8dee2aaSAndroid Build Coastguard Worker SkISize GrSurfaceProxy::backingStoreDimensions() const {
253*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isFullyLazy());
254*c8dee2aaSAndroid Build Coastguard Worker     if (fTarget) {
255*c8dee2aaSAndroid Build Coastguard Worker         return fTarget->dimensions();
256*c8dee2aaSAndroid Build Coastguard Worker     }
257*c8dee2aaSAndroid Build Coastguard Worker 
258*c8dee2aaSAndroid Build Coastguard Worker     if (SkBackingFit::kExact == fFit) {
259*c8dee2aaSAndroid Build Coastguard Worker         return fDimensions;
260*c8dee2aaSAndroid Build Coastguard Worker     }
261*c8dee2aaSAndroid Build Coastguard Worker     return skgpu::GetApproxSize(fDimensions);
262*c8dee2aaSAndroid Build Coastguard Worker }
263*c8dee2aaSAndroid Build Coastguard Worker 
isFunctionallyExact() const264*c8dee2aaSAndroid Build Coastguard Worker bool GrSurfaceProxy::isFunctionallyExact() const {
265*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isFullyLazy());
266*c8dee2aaSAndroid Build Coastguard Worker     return fFit == SkBackingFit::kExact ||
267*c8dee2aaSAndroid Build Coastguard Worker            fDimensions == skgpu::GetApproxSize(fDimensions);
268*c8dee2aaSAndroid Build Coastguard Worker }
269*c8dee2aaSAndroid Build Coastguard Worker 
isFormatCompressed(const GrCaps * caps) const270*c8dee2aaSAndroid Build Coastguard Worker bool GrSurfaceProxy::isFormatCompressed(const GrCaps* caps) const {
271*c8dee2aaSAndroid Build Coastguard Worker     return caps->isFormatCompressed(this->backendFormat());
272*c8dee2aaSAndroid Build Coastguard Worker }
273*c8dee2aaSAndroid Build Coastguard Worker 
274*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
validate(GrContext_Base * context) const275*c8dee2aaSAndroid Build Coastguard Worker void GrSurfaceProxy::validate(GrContext_Base* context) const {
276*c8dee2aaSAndroid Build Coastguard Worker     if (fTarget) {
277*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fTarget->getContext()->priv().matches(context));
278*c8dee2aaSAndroid Build Coastguard Worker     }
279*c8dee2aaSAndroid Build Coastguard Worker }
280*c8dee2aaSAndroid Build Coastguard Worker #endif
281*c8dee2aaSAndroid Build Coastguard Worker 
Copy(GrRecordingContext * rContext,sk_sp<GrSurfaceProxy> src,GrSurfaceOrigin origin,skgpu::Mipmapped mipmapped,SkIRect srcRect,SkBackingFit fit,skgpu::Budgeted budgeted,std::string_view label,RectsMustMatch rectsMustMatch,sk_sp<GrRenderTask> * outTask)282*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* rContext,
283*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<GrSurfaceProxy> src,
284*c8dee2aaSAndroid Build Coastguard Worker                                            GrSurfaceOrigin origin,
285*c8dee2aaSAndroid Build Coastguard Worker                                            skgpu::Mipmapped mipmapped,
286*c8dee2aaSAndroid Build Coastguard Worker                                            SkIRect srcRect,
287*c8dee2aaSAndroid Build Coastguard Worker                                            SkBackingFit fit,
288*c8dee2aaSAndroid Build Coastguard Worker                                            skgpu::Budgeted budgeted,
289*c8dee2aaSAndroid Build Coastguard Worker                                            std::string_view label,
290*c8dee2aaSAndroid Build Coastguard Worker                                            RectsMustMatch rectsMustMatch,
291*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<GrRenderTask>* outTask) {
292*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!src->isFullyLazy());
293*c8dee2aaSAndroid Build Coastguard Worker     int width;
294*c8dee2aaSAndroid Build Coastguard Worker     int height;
295*c8dee2aaSAndroid Build Coastguard Worker 
296*c8dee2aaSAndroid Build Coastguard Worker     SkIPoint dstPoint;
297*c8dee2aaSAndroid Build Coastguard Worker     if (rectsMustMatch == RectsMustMatch::kYes) {
298*c8dee2aaSAndroid Build Coastguard Worker         width = src->width();
299*c8dee2aaSAndroid Build Coastguard Worker         height = src->height();
300*c8dee2aaSAndroid Build Coastguard Worker         dstPoint = {srcRect.fLeft, srcRect.fTop};
301*c8dee2aaSAndroid Build Coastguard Worker     } else {
302*c8dee2aaSAndroid Build Coastguard Worker         width = srcRect.width();
303*c8dee2aaSAndroid Build Coastguard Worker         height = srcRect.height();
304*c8dee2aaSAndroid Build Coastguard Worker         dstPoint = {0, 0};
305*c8dee2aaSAndroid Build Coastguard Worker     }
306*c8dee2aaSAndroid Build Coastguard Worker 
307*c8dee2aaSAndroid Build Coastguard Worker     if (!srcRect.intersect(SkIRect::MakeSize(src->dimensions()))) {
308*c8dee2aaSAndroid Build Coastguard Worker         return {};
309*c8dee2aaSAndroid Build Coastguard Worker     }
310*c8dee2aaSAndroid Build Coastguard Worker     auto format = src->backendFormat().makeTexture2D();
311*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(format.isValid());
312*c8dee2aaSAndroid Build Coastguard Worker 
313*c8dee2aaSAndroid Build Coastguard Worker     if (src->backendFormat().textureType() != GrTextureType::kExternal) {
314*c8dee2aaSAndroid Build Coastguard Worker         GrImageInfo info(GrColorType::kUnknown, kUnknown_SkAlphaType, nullptr, {width, height});
315*c8dee2aaSAndroid Build Coastguard Worker         auto dstContext = rContext->priv().makeSC(info,
316*c8dee2aaSAndroid Build Coastguard Worker                                                   format,
317*c8dee2aaSAndroid Build Coastguard Worker                                                   label,
318*c8dee2aaSAndroid Build Coastguard Worker                                                   fit,
319*c8dee2aaSAndroid Build Coastguard Worker                                                   origin,
320*c8dee2aaSAndroid Build Coastguard Worker                                                   GrRenderable::kNo,
321*c8dee2aaSAndroid Build Coastguard Worker                                                   1,
322*c8dee2aaSAndroid Build Coastguard Worker                                                   mipmapped,
323*c8dee2aaSAndroid Build Coastguard Worker                                                   src->isProtected(),
324*c8dee2aaSAndroid Build Coastguard Worker                                                   budgeted);
325*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<GrRenderTask> copyTask;
326*c8dee2aaSAndroid Build Coastguard Worker         if (dstContext && (copyTask = dstContext->copy(src, srcRect, dstPoint))) {
327*c8dee2aaSAndroid Build Coastguard Worker             if (outTask) {
328*c8dee2aaSAndroid Build Coastguard Worker                 *outTask = std::move(copyTask);
329*c8dee2aaSAndroid Build Coastguard Worker             }
330*c8dee2aaSAndroid Build Coastguard Worker             return dstContext->asSurfaceProxyRef();
331*c8dee2aaSAndroid Build Coastguard Worker         }
332*c8dee2aaSAndroid Build Coastguard Worker     }
333*c8dee2aaSAndroid Build Coastguard Worker     if (src->asTextureProxy()) {
334*c8dee2aaSAndroid Build Coastguard Worker         auto dstContext = rContext->priv().makeSFC(kUnknown_SkAlphaType,
335*c8dee2aaSAndroid Build Coastguard Worker                                                    nullptr,
336*c8dee2aaSAndroid Build Coastguard Worker                                                    {width, height},
337*c8dee2aaSAndroid Build Coastguard Worker                                                    fit,
338*c8dee2aaSAndroid Build Coastguard Worker                                                    format,
339*c8dee2aaSAndroid Build Coastguard Worker                                                    1,
340*c8dee2aaSAndroid Build Coastguard Worker                                                    mipmapped,
341*c8dee2aaSAndroid Build Coastguard Worker                                                    src->isProtected(),
342*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Swizzle::RGBA(),
343*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Swizzle::RGBA(),
344*c8dee2aaSAndroid Build Coastguard Worker                                                    origin,
345*c8dee2aaSAndroid Build Coastguard Worker                                                    budgeted,
346*c8dee2aaSAndroid Build Coastguard Worker                                                    label);
347*c8dee2aaSAndroid Build Coastguard Worker         GrSurfaceProxyView view(std::move(src), origin, skgpu::Swizzle::RGBA());
348*c8dee2aaSAndroid Build Coastguard Worker         if (dstContext && dstContext->blitTexture(std::move(view), srcRect, dstPoint)) {
349*c8dee2aaSAndroid Build Coastguard Worker             if (outTask) {
350*c8dee2aaSAndroid Build Coastguard Worker                 *outTask = dstContext->refRenderTask();
351*c8dee2aaSAndroid Build Coastguard Worker             }
352*c8dee2aaSAndroid Build Coastguard Worker             return dstContext->asSurfaceProxyRef();
353*c8dee2aaSAndroid Build Coastguard Worker         }
354*c8dee2aaSAndroid Build Coastguard Worker     }
355*c8dee2aaSAndroid Build Coastguard Worker     // Can't use backend copies or draws.
356*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
357*c8dee2aaSAndroid Build Coastguard Worker }
358*c8dee2aaSAndroid Build Coastguard Worker 
Copy(GrRecordingContext * context,sk_sp<GrSurfaceProxy> src,GrSurfaceOrigin origin,skgpu::Mipmapped mipmapped,SkBackingFit fit,skgpu::Budgeted budgeted,std::string_view label,sk_sp<GrRenderTask> * outTask)359*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
360*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<GrSurfaceProxy> src,
361*c8dee2aaSAndroid Build Coastguard Worker                                            GrSurfaceOrigin origin,
362*c8dee2aaSAndroid Build Coastguard Worker                                            skgpu::Mipmapped mipmapped,
363*c8dee2aaSAndroid Build Coastguard Worker                                            SkBackingFit fit,
364*c8dee2aaSAndroid Build Coastguard Worker                                            skgpu::Budgeted budgeted,
365*c8dee2aaSAndroid Build Coastguard Worker                                            std::string_view label,
366*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<GrRenderTask>* outTask) {
367*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!src->isFullyLazy());
368*c8dee2aaSAndroid Build Coastguard Worker     auto rect = SkIRect::MakeSize(src->dimensions());
369*c8dee2aaSAndroid Build Coastguard Worker     return Copy(context,
370*c8dee2aaSAndroid Build Coastguard Worker                 std::move(src),
371*c8dee2aaSAndroid Build Coastguard Worker                 origin,
372*c8dee2aaSAndroid Build Coastguard Worker                 mipmapped,
373*c8dee2aaSAndroid Build Coastguard Worker                 rect,
374*c8dee2aaSAndroid Build Coastguard Worker                 fit,
375*c8dee2aaSAndroid Build Coastguard Worker                 budgeted,
376*c8dee2aaSAndroid Build Coastguard Worker                 label,
377*c8dee2aaSAndroid Build Coastguard Worker                 RectsMustMatch::kNo,
378*c8dee2aaSAndroid Build Coastguard Worker                 outTask);
379*c8dee2aaSAndroid Build Coastguard Worker }
380*c8dee2aaSAndroid Build Coastguard Worker 
381*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
testingOnly_getBackingRefCnt() const382*c8dee2aaSAndroid Build Coastguard Worker int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
383*c8dee2aaSAndroid Build Coastguard Worker     if (fTarget) {
384*c8dee2aaSAndroid Build Coastguard Worker         return fTarget->testingOnly_getRefCnt();
385*c8dee2aaSAndroid Build Coastguard Worker     }
386*c8dee2aaSAndroid Build Coastguard Worker 
387*c8dee2aaSAndroid Build Coastguard Worker     return -1; // no backing GrSurface
388*c8dee2aaSAndroid Build Coastguard Worker }
389*c8dee2aaSAndroid Build Coastguard Worker 
testingOnly_getFlags() const390*c8dee2aaSAndroid Build Coastguard Worker GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
391*c8dee2aaSAndroid Build Coastguard Worker     return fSurfaceFlags;
392*c8dee2aaSAndroid Build Coastguard Worker }
393*c8dee2aaSAndroid Build Coastguard Worker 
dump() const394*c8dee2aaSAndroid Build Coastguard Worker SkString GrSurfaceProxy::dump() const {
395*c8dee2aaSAndroid Build Coastguard Worker     SkString tmp;
396*c8dee2aaSAndroid Build Coastguard Worker 
397*c8dee2aaSAndroid Build Coastguard Worker     tmp.appendf("proxyID: %u - surfaceID: %u",
398*c8dee2aaSAndroid Build Coastguard Worker                 this->uniqueID().asUInt(),
399*c8dee2aaSAndroid Build Coastguard Worker                 this->peekSurface() ? this->peekSurface()->uniqueID().asUInt()
400*c8dee2aaSAndroid Build Coastguard Worker                                     : -1);
401*c8dee2aaSAndroid Build Coastguard Worker     return tmp;
402*c8dee2aaSAndroid Build Coastguard Worker }
403*c8dee2aaSAndroid Build Coastguard Worker 
404*c8dee2aaSAndroid Build Coastguard Worker #endif
405*c8dee2aaSAndroid Build Coastguard Worker 
exactify()406*c8dee2aaSAndroid Build Coastguard Worker void GrSurfaceProxyPriv::exactify() {
407*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fProxy->isFullyLazy());
408*c8dee2aaSAndroid Build Coastguard Worker     if (this->isExact()) {
409*c8dee2aaSAndroid Build Coastguard Worker         return;
410*c8dee2aaSAndroid Build Coastguard Worker     }
411*c8dee2aaSAndroid Build Coastguard Worker 
412*c8dee2aaSAndroid Build Coastguard Worker     // The kApprox case. Setting the proxy's width & height to the backing-store width & height
413*c8dee2aaSAndroid Build Coastguard Worker     // could have side-effects going forward, since we're obliterating the area of interest
414*c8dee2aaSAndroid Build Coastguard Worker     // information. This is only used by SkSpecialImage when it's determined that sampling will
415*c8dee2aaSAndroid Build Coastguard Worker     // not access beyond the safe known region (the current value of fProxy->fDimensions). If
416*c8dee2aaSAndroid Build Coastguard Worker     // the proxy is instantiated, update the proxy's dimensions to match. Otherwise update them
417*c8dee2aaSAndroid Build Coastguard Worker     // to the backing-store dimensions.
418*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
419*c8dee2aaSAndroid Build Coastguard Worker     fProxy->fDimensions = fProxy->fTarget ? fProxy->fTarget->dimensions()
420*c8dee2aaSAndroid Build Coastguard Worker                                           : fProxy->backingStoreDimensions();
421*c8dee2aaSAndroid Build Coastguard Worker     fProxy->fFit = SkBackingFit::kExact;
422*c8dee2aaSAndroid Build Coastguard Worker }
423*c8dee2aaSAndroid Build Coastguard Worker 
doLazyInstantiation(GrResourceProvider * resourceProvider)424*c8dee2aaSAndroid Build Coastguard Worker bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
425*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fProxy->isLazy());
426*c8dee2aaSAndroid Build Coastguard Worker 
427*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrSurface> surface;
428*c8dee2aaSAndroid Build Coastguard Worker     if (const auto& uniqueKey = fProxy->getUniqueKey(); uniqueKey.isValid()) {
429*c8dee2aaSAndroid Build Coastguard Worker         // First try to reattach to a cached version if the proxy is uniquely keyed
430*c8dee2aaSAndroid Build Coastguard Worker         surface = resourceProvider->findByUniqueKey<GrSurface>(uniqueKey);
431*c8dee2aaSAndroid Build Coastguard Worker     }
432*c8dee2aaSAndroid Build Coastguard Worker 
433*c8dee2aaSAndroid Build Coastguard Worker     bool syncKey = true;
434*c8dee2aaSAndroid Build Coastguard Worker     bool releaseCallback = false;
435*c8dee2aaSAndroid Build Coastguard Worker     if (!surface) {
436*c8dee2aaSAndroid Build Coastguard Worker         auto result = fProxy->fLazyInstantiateCallback(resourceProvider, fProxy->callbackDesc());
437*c8dee2aaSAndroid Build Coastguard Worker         surface = std::move(result.fSurface);
438*c8dee2aaSAndroid Build Coastguard Worker         syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
439*c8dee2aaSAndroid Build Coastguard Worker         releaseCallback = surface && result.fReleaseCallback;
440*c8dee2aaSAndroid Build Coastguard Worker     }
441*c8dee2aaSAndroid Build Coastguard Worker     if (!surface) {
442*c8dee2aaSAndroid Build Coastguard Worker         fProxy->fDimensions.setEmpty();
443*c8dee2aaSAndroid Build Coastguard Worker         return false;
444*c8dee2aaSAndroid Build Coastguard Worker     }
445*c8dee2aaSAndroid Build Coastguard Worker 
446*c8dee2aaSAndroid Build Coastguard Worker     if (fProxy->isFullyLazy()) {
447*c8dee2aaSAndroid Build Coastguard Worker         // This was a fully lazy proxy. We need to fill in the width & height. For partially
448*c8dee2aaSAndroid Build Coastguard Worker         // lazy proxies we must preserve the original width & height since that indicates
449*c8dee2aaSAndroid Build Coastguard Worker         // the content area.
450*c8dee2aaSAndroid Build Coastguard Worker         fProxy->fDimensions = surface->dimensions();
451*c8dee2aaSAndroid Build Coastguard Worker     }
452*c8dee2aaSAndroid Build Coastguard Worker 
453*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fProxy->width() <= surface->width());
454*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fProxy->height() <= surface->height());
455*c8dee2aaSAndroid Build Coastguard Worker 
456*c8dee2aaSAndroid Build Coastguard Worker     if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
457*c8dee2aaSAndroid Build Coastguard Worker         texProxy->setTargetKeySync(syncKey);
458*c8dee2aaSAndroid Build Coastguard Worker         if (syncKey) {
459*c8dee2aaSAndroid Build Coastguard Worker             const skgpu::UniqueKey& key = texProxy->getUniqueKey();
460*c8dee2aaSAndroid Build Coastguard Worker             if (key.isValid()) {
461*c8dee2aaSAndroid Build Coastguard Worker                 if (!surface->asTexture()->getUniqueKey().isValid()) {
462*c8dee2aaSAndroid Build Coastguard Worker                     // If 'surface' is newly created, attach the unique key
463*c8dee2aaSAndroid Build Coastguard Worker                     resourceProvider->assignUniqueKeyToResource(key, surface.get());
464*c8dee2aaSAndroid Build Coastguard Worker                 } else {
465*c8dee2aaSAndroid Build Coastguard Worker                     // otherwise we had better have reattached to a cached version
466*c8dee2aaSAndroid Build Coastguard Worker                     SkASSERT(surface->asTexture()->getUniqueKey() == key);
467*c8dee2aaSAndroid Build Coastguard Worker                 }
468*c8dee2aaSAndroid Build Coastguard Worker             } else {
469*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(!surface->getUniqueKey().isValid());
470*c8dee2aaSAndroid Build Coastguard Worker             }
471*c8dee2aaSAndroid Build Coastguard Worker         }
472*c8dee2aaSAndroid Build Coastguard Worker     }
473*c8dee2aaSAndroid Build Coastguard Worker 
474*c8dee2aaSAndroid Build Coastguard Worker     this->assign(std::move(surface));
475*c8dee2aaSAndroid Build Coastguard Worker     if (releaseCallback) {
476*c8dee2aaSAndroid Build Coastguard Worker         fProxy->fLazyInstantiateCallback = nullptr;
477*c8dee2aaSAndroid Build Coastguard Worker     }
478*c8dee2aaSAndroid Build Coastguard Worker 
479*c8dee2aaSAndroid Build Coastguard Worker     return true;
480*c8dee2aaSAndroid Build Coastguard Worker }
481*c8dee2aaSAndroid Build Coastguard Worker 
482*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
validateSurface(const GrSurface * surface)483*c8dee2aaSAndroid Build Coastguard Worker void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
484*c8dee2aaSAndroid Build Coastguard Worker     SkASSERTF(surface->backendFormat() == fFormat, "%s != %s",
485*c8dee2aaSAndroid Build Coastguard Worker               surface->backendFormat().toStr().c_str(), fFormat.toStr().c_str());
486*c8dee2aaSAndroid Build Coastguard Worker 
487*c8dee2aaSAndroid Build Coastguard Worker     this->onValidateSurface(surface);
488*c8dee2aaSAndroid Build Coastguard Worker }
489*c8dee2aaSAndroid Build Coastguard Worker #endif
490