xref: /aosp_15_r20/external/skia/src/gpu/graphite/TextureProxy.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/gpu/graphite/TextureProxy.h"
9 
10 #include "include/gpu/graphite/Recorder.h"
11 #include "src/core/SkMipmap.h"
12 #include "src/gpu/graphite/Caps.h"
13 #include "src/gpu/graphite/RecorderPriv.h"
14 #include "src/gpu/graphite/ResourceProvider.h"
15 #include "src/gpu/graphite/ScratchResourceManager.h"
16 #include "src/gpu/graphite/Texture.h"
17 #include "src/gpu/graphite/TextureUtils.h"
18 
19 namespace skgpu::graphite {
20 
TextureProxy(SkISize dimensions,const TextureInfo & info,std::string_view label,skgpu::Budgeted budgeted)21 TextureProxy::TextureProxy(SkISize dimensions,
22                            const TextureInfo& info,
23                            std::string_view label,
24                            skgpu::Budgeted budgeted)
25         : fDimensions(dimensions)
26         , fInfo(info)
27         , fLabel(label)
28         , fBudgeted(budgeted)
29         , fVolatile(Volatile::kNo) {
30     SkASSERT(fInfo.isValid());
31 }
32 
TextureProxy(sk_sp<Texture> texture)33 TextureProxy::TextureProxy(sk_sp<Texture> texture)
34         : fDimensions(texture->dimensions())
35         , fInfo(texture->textureInfo())
36         , fLabel(texture->getLabel())
37         , fBudgeted(texture->budgeted())
38         , fVolatile(Volatile::kNo)
39         , fTexture(std::move(texture)) {
40     SkASSERT(fInfo.isValid());
41 }
42 
TextureProxy(SkISize dimensions,const TextureInfo & textureInfo,skgpu::Budgeted budgeted,Volatile isVolatile,LazyInstantiateCallback && callback)43 TextureProxy::TextureProxy(SkISize dimensions,
44                            const TextureInfo& textureInfo,
45                            skgpu::Budgeted budgeted,
46                            Volatile isVolatile,
47                            LazyInstantiateCallback&& callback)
48         : fDimensions(dimensions)
49         , fInfo(textureInfo)
50         , fBudgeted(budgeted)
51         , fVolatile(isVolatile)
52         , fLazyInstantiateCallback(std::move(callback)) {
53     SkASSERT(fInfo.isValid());
54     SkASSERT(fLazyInstantiateCallback);
55 }
56 
~TextureProxy()57 TextureProxy::~TextureProxy() {}
58 
dimensions() const59 SkISize TextureProxy::dimensions() const {
60     SkASSERT(!this->isFullyLazy() || this->isInstantiated());
61     return this->isInstantiated() ? fTexture->dimensions() : fDimensions;
62 }
63 
isLazy() const64 bool TextureProxy::isLazy() const {
65     return SkToBool(fLazyInstantiateCallback);
66 }
67 
isFullyLazy() const68 bool TextureProxy::isFullyLazy() const {
69     bool result = fDimensions.width() < 0;
70     SkASSERT(result == (fDimensions.height() < 0));
71     SkASSERT(!result || this->isLazy());
72     return result;
73 }
74 
isVolatile() const75 bool TextureProxy::isVolatile() const {
76     SkASSERT(fVolatile == Volatile::kNo || SkToBool(fLazyInstantiateCallback));
77 
78     return fVolatile == Volatile::kYes;
79 }
80 
isProtected() const81 bool TextureProxy::isProtected() const {
82     return fInfo.isProtected() == Protected::kYes;
83 }
84 
uninstantiatedGpuMemorySize() const85 size_t TextureProxy::uninstantiatedGpuMemorySize() const {
86     return ComputeSize(fDimensions, fInfo);
87 }
88 
instantiate(ResourceProvider * resourceProvider)89 bool TextureProxy::instantiate(ResourceProvider* resourceProvider) {
90     SkASSERT(!this->isLazy());
91 
92     if (fTexture) {
93         return true;
94     }
95 
96     fTexture = resourceProvider->findOrCreateScratchTexture(fDimensions, fInfo, fLabel, fBudgeted);
97     if (!fTexture) {
98         return false;
99     }
100     SkDEBUGCODE(this->validateTexture(fTexture.get()));
101     return true;
102 }
103 
lazyInstantiate(ResourceProvider * resourceProvider)104 bool TextureProxy::lazyInstantiate(ResourceProvider* resourceProvider) {
105     SkASSERT(this->isLazy());
106 
107     if (fTexture) {
108         return true;
109     }
110 
111     fTexture = fLazyInstantiateCallback(resourceProvider);
112     if (!fTexture) {
113         return false;
114     }
115     SkDEBUGCODE(this->validateTexture(fTexture.get()));
116     return true;
117 }
118 
InstantiateIfNotLazy(ResourceProvider * resourceProvider,TextureProxy * textureProxy)119 bool TextureProxy::InstantiateIfNotLazy(ResourceProvider* resourceProvider,
120                                         TextureProxy* textureProxy) {
121     if (textureProxy->isLazy()) {
122         return true;
123     }
124 
125     return textureProxy->instantiate(resourceProvider);
126 }
127 
InstantiateIfNotLazy(ScratchResourceManager * scratchManager,TextureProxy * textureProxy)128 bool TextureProxy::InstantiateIfNotLazy(ScratchResourceManager* scratchManager,
129                                         TextureProxy* textureProxy) {
130     if (textureProxy->isLazy() || textureProxy->isInstantiated()) {
131         return true;
132     }
133 
134     textureProxy->fTexture = scratchManager->getScratchTexture(textureProxy->dimensions(),
135                                                                textureProxy->textureInfo(),
136                                                                textureProxy->fLabel);
137     if (!textureProxy->fTexture) {
138         return false;
139     }
140     SkDEBUGCODE(textureProxy->validateTexture(textureProxy->fTexture.get()));
141     return true;
142 }
143 
144 
deinstantiate()145 void TextureProxy::deinstantiate() {
146     SkASSERT(fVolatile == Volatile::kYes && SkToBool(fLazyInstantiateCallback));
147 
148     fTexture.reset();
149 }
150 
refTexture() const151 sk_sp<Texture> TextureProxy::refTexture() const {
152     return fTexture;
153 }
154 
texture() const155 const Texture* TextureProxy::texture() const {
156     return fTexture.get();
157 }
158 
Make(const Caps * caps,ResourceProvider * resourceProvider,SkISize dimensions,const TextureInfo & textureInfo,std::string_view label,skgpu::Budgeted budgeted)159 sk_sp<TextureProxy> TextureProxy::Make(const Caps* caps,
160                                        ResourceProvider* resourceProvider,
161                                        SkISize dimensions,
162                                        const TextureInfo& textureInfo,
163                                        std::string_view label,
164                                        skgpu::Budgeted budgeted) {
165     if (dimensions.width() < 1 || dimensions.height() < 1 ||
166         dimensions.width() > caps->maxTextureSize() ||
167         dimensions.height() > caps->maxTextureSize() ||
168         !textureInfo.isValid()) {
169         return nullptr;
170     }
171 
172     sk_sp<TextureProxy> proxy{new TextureProxy(dimensions,
173                                                textureInfo,
174                                                std::move(label),
175                                                budgeted)};
176     if (budgeted == Budgeted::kNo) {
177         // Instantiate immediately to avoid races later on if the client starts to use the wrapping
178         // object on multiple threads.
179         if (!proxy->instantiate(resourceProvider)) {
180             return nullptr;
181         }
182     }
183     return proxy;
184 }
185 
MakeLazy(const Caps * caps,SkISize dimensions,const TextureInfo & textureInfo,skgpu::Budgeted budgeted,Volatile isVolatile,LazyInstantiateCallback && callback)186 sk_sp<TextureProxy> TextureProxy::MakeLazy(const Caps* caps,
187                                            SkISize dimensions,
188                                            const TextureInfo& textureInfo,
189                                            skgpu::Budgeted budgeted,
190                                            Volatile isVolatile,
191                                            LazyInstantiateCallback&& callback) {
192     SkASSERT(textureInfo.isValid());
193     if (dimensions.width() < 1 || dimensions.height() < 1 ||
194         dimensions.width() > caps->maxTextureSize() ||
195         dimensions.height() > caps->maxTextureSize()) {
196         return nullptr;
197     }
198 
199     return sk_sp<TextureProxy>(new TextureProxy(dimensions,
200                                                 textureInfo,
201                                                 budgeted,
202                                                 isVolatile,
203                                                 std::move(callback)));
204 }
205 
MakeFullyLazy(const TextureInfo & textureInfo,skgpu::Budgeted budgeted,Volatile isVolatile,LazyInstantiateCallback && callback)206 sk_sp<TextureProxy> TextureProxy::MakeFullyLazy(const TextureInfo& textureInfo,
207                                                 skgpu::Budgeted budgeted,
208                                                 Volatile isVolatile,
209                                                 LazyInstantiateCallback&& callback) {
210     SkASSERT(textureInfo.isValid());
211 
212     return sk_sp<TextureProxy>(new TextureProxy(SkISize::Make(-1, -1),
213                                                 textureInfo,
214                                                 budgeted,
215                                                 isVolatile,
216                                                 std::move(callback)));
217 }
218 
Wrap(sk_sp<Texture> texture)219 sk_sp<TextureProxy> TextureProxy::Wrap(sk_sp<Texture> texture) {
220     return sk_sp<TextureProxy>(new TextureProxy(std::move(texture)));
221 }
222 
223 #ifdef SK_DEBUG
validateTexture(const Texture * texture)224 void TextureProxy::validateTexture(const Texture* texture) {
225     SkASSERT(this->isFullyLazy() || fDimensions == texture->dimensions());
226     SkASSERTF(fInfo.isCompatible(texture->textureInfo()),
227               "proxy->fInfo[%s] incompatible with texture->fInfo[%s]",
228               fInfo.toString().c_str(),
229               texture->textureInfo().toString().c_str());
230 }
231 #endif
232 
233 } // namespace skgpu::graphite
234