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