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