xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gl/GrGLTexture.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLTexture.h"
8*c8dee2aaSAndroid Build Coastguard Worker 
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTraceMemoryDump.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkImageGanesh.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/gl/GrGLFunctions.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/gl/GrGLInterface.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLBackendSurfacePriv.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLCaps.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLDefines.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLGpu.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLUtil.h"
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
26*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
27*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
28*c8dee2aaSAndroid Build Coastguard Worker #include <string>
29*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker #define GPUGL static_cast<GrGLGpu*>(this->getGpu())
32*c8dee2aaSAndroid Build Coastguard Worker #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
33*c8dee2aaSAndroid Build Coastguard Worker 
TextureTypeFromTarget(GrGLenum target)34*c8dee2aaSAndroid Build Coastguard Worker GrTextureType GrGLTexture::TextureTypeFromTarget(GrGLenum target) {
35*c8dee2aaSAndroid Build Coastguard Worker     switch (target) {
36*c8dee2aaSAndroid Build Coastguard Worker         case GR_GL_TEXTURE_2D:
37*c8dee2aaSAndroid Build Coastguard Worker             return GrTextureType::k2D;
38*c8dee2aaSAndroid Build Coastguard Worker         case GR_GL_TEXTURE_RECTANGLE:
39*c8dee2aaSAndroid Build Coastguard Worker             return GrTextureType::kRectangle;
40*c8dee2aaSAndroid Build Coastguard Worker         case GR_GL_TEXTURE_EXTERNAL:
41*c8dee2aaSAndroid Build Coastguard Worker             return GrTextureType::kExternal;
42*c8dee2aaSAndroid Build Coastguard Worker     }
43*c8dee2aaSAndroid Build Coastguard Worker     SK_ABORT("Unexpected texture target");
44*c8dee2aaSAndroid Build Coastguard Worker }
45*c8dee2aaSAndroid Build Coastguard Worker 
target_from_texture_type(GrTextureType type)46*c8dee2aaSAndroid Build Coastguard Worker static inline GrGLenum target_from_texture_type(GrTextureType type) {
47*c8dee2aaSAndroid Build Coastguard Worker     switch (type) {
48*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::k2D:
49*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_TEXTURE_2D;
50*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::kRectangle:
51*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_TEXTURE_RECTANGLE;
52*c8dee2aaSAndroid Build Coastguard Worker         case GrTextureType::kExternal:
53*c8dee2aaSAndroid Build Coastguard Worker             return GR_GL_TEXTURE_EXTERNAL;
54*c8dee2aaSAndroid Build Coastguard Worker         default:
55*c8dee2aaSAndroid Build Coastguard Worker             SK_ABORT("Unexpected texture target");
56*c8dee2aaSAndroid Build Coastguard Worker     }
57*c8dee2aaSAndroid Build Coastguard Worker     SK_ABORT("Unexpected texture type");
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker 
60*c8dee2aaSAndroid Build Coastguard Worker // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
GrGLTexture(GrGLGpu * gpu,skgpu::Budgeted budgeted,const Desc & desc,GrMipmapStatus mipmapStatus,std::string_view label)61*c8dee2aaSAndroid Build Coastguard Worker GrGLTexture::GrGLTexture(GrGLGpu* gpu,
62*c8dee2aaSAndroid Build Coastguard Worker                          skgpu::Budgeted budgeted,
63*c8dee2aaSAndroid Build Coastguard Worker                          const Desc& desc,
64*c8dee2aaSAndroid Build Coastguard Worker                          GrMipmapStatus mipmapStatus,
65*c8dee2aaSAndroid Build Coastguard Worker                          std::string_view label)
66*c8dee2aaSAndroid Build Coastguard Worker         : GrSurface(gpu, desc.fSize, desc.fIsProtected, label)
67*c8dee2aaSAndroid Build Coastguard Worker         , GrTexture(gpu,
68*c8dee2aaSAndroid Build Coastguard Worker                     desc.fSize,
69*c8dee2aaSAndroid Build Coastguard Worker                     desc.fIsProtected,
70*c8dee2aaSAndroid Build Coastguard Worker                     TextureTypeFromTarget(desc.fTarget),
71*c8dee2aaSAndroid Build Coastguard Worker                     mipmapStatus,
72*c8dee2aaSAndroid Build Coastguard Worker                     label)
73*c8dee2aaSAndroid Build Coastguard Worker         , fParameters(sk_make_sp<GrGLTextureParameters>()) {
74*c8dee2aaSAndroid Build Coastguard Worker     this->init(desc);
75*c8dee2aaSAndroid Build Coastguard Worker     this->registerWithCache(budgeted);
76*c8dee2aaSAndroid Build Coastguard Worker     if (GrGLFormatIsCompressed(desc.fFormat)) {
77*c8dee2aaSAndroid Build Coastguard Worker         this->setReadOnly();
78*c8dee2aaSAndroid Build Coastguard Worker     }
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker 
GrGLTexture(GrGLGpu * gpu,const Desc & desc,GrMipmapStatus mipmapStatus,sk_sp<GrGLTextureParameters> parameters,GrWrapCacheable cacheable,GrIOType ioType,std::string_view label)81*c8dee2aaSAndroid Build Coastguard Worker GrGLTexture::GrGLTexture(GrGLGpu* gpu, const Desc& desc, GrMipmapStatus mipmapStatus,
82*c8dee2aaSAndroid Build Coastguard Worker                          sk_sp<GrGLTextureParameters> parameters, GrWrapCacheable cacheable,
83*c8dee2aaSAndroid Build Coastguard Worker                          GrIOType ioType, std::string_view label)
84*c8dee2aaSAndroid Build Coastguard Worker         : GrSurface(gpu, desc.fSize, desc.fIsProtected, label)
85*c8dee2aaSAndroid Build Coastguard Worker         , GrTexture(gpu,
86*c8dee2aaSAndroid Build Coastguard Worker                     desc.fSize,
87*c8dee2aaSAndroid Build Coastguard Worker                     desc.fIsProtected,
88*c8dee2aaSAndroid Build Coastguard Worker                     TextureTypeFromTarget(desc.fTarget),
89*c8dee2aaSAndroid Build Coastguard Worker                     mipmapStatus,
90*c8dee2aaSAndroid Build Coastguard Worker                     label)
91*c8dee2aaSAndroid Build Coastguard Worker         , fParameters(std::move(parameters)) {
92*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fParameters);
93*c8dee2aaSAndroid Build Coastguard Worker     this->init(desc);
94*c8dee2aaSAndroid Build Coastguard Worker     this->registerWithCacheWrapped(cacheable);
95*c8dee2aaSAndroid Build Coastguard Worker     if (ioType == kRead_GrIOType) {
96*c8dee2aaSAndroid Build Coastguard Worker         this->setReadOnly();
97*c8dee2aaSAndroid Build Coastguard Worker     }
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker 
GrGLTexture(GrGLGpu * gpu,const Desc & desc,sk_sp<GrGLTextureParameters> parameters,GrMipmapStatus mipmapStatus,std::string_view label)100*c8dee2aaSAndroid Build Coastguard Worker GrGLTexture::GrGLTexture(GrGLGpu* gpu,
101*c8dee2aaSAndroid Build Coastguard Worker                          const Desc& desc,
102*c8dee2aaSAndroid Build Coastguard Worker                          sk_sp<GrGLTextureParameters> parameters,
103*c8dee2aaSAndroid Build Coastguard Worker                          GrMipmapStatus mipmapStatus,
104*c8dee2aaSAndroid Build Coastguard Worker                          std::string_view label)
105*c8dee2aaSAndroid Build Coastguard Worker         : GrSurface(gpu, desc.fSize, desc.fIsProtected, label)
106*c8dee2aaSAndroid Build Coastguard Worker         , GrTexture(gpu,
107*c8dee2aaSAndroid Build Coastguard Worker                     desc.fSize,
108*c8dee2aaSAndroid Build Coastguard Worker                     desc.fIsProtected,
109*c8dee2aaSAndroid Build Coastguard Worker                     TextureTypeFromTarget(desc.fTarget),
110*c8dee2aaSAndroid Build Coastguard Worker                     mipmapStatus,
111*c8dee2aaSAndroid Build Coastguard Worker                     label) {
112*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(parameters || desc.fOwnership == GrBackendObjectOwnership::kOwned);
113*c8dee2aaSAndroid Build Coastguard Worker     fParameters = parameters ? std::move(parameters) : sk_make_sp<GrGLTextureParameters>();
114*c8dee2aaSAndroid Build Coastguard Worker     this->init(desc);
115*c8dee2aaSAndroid Build Coastguard Worker }
116*c8dee2aaSAndroid Build Coastguard Worker 
init(const Desc & desc)117*c8dee2aaSAndroid Build Coastguard Worker void GrGLTexture::init(const Desc& desc) {
118*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(0 != desc.fID);
119*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrGLFormat::kUnknown != desc.fFormat);
120*c8dee2aaSAndroid Build Coastguard Worker     fID = desc.fID;
121*c8dee2aaSAndroid Build Coastguard Worker     fFormat = desc.fFormat;
122*c8dee2aaSAndroid Build Coastguard Worker     fTextureIDOwnership = desc.fOwnership;
123*c8dee2aaSAndroid Build Coastguard Worker }
124*c8dee2aaSAndroid Build Coastguard Worker 
target() const125*c8dee2aaSAndroid Build Coastguard Worker GrGLenum GrGLTexture::target() const { return target_from_texture_type(this->textureType()); }
126*c8dee2aaSAndroid Build Coastguard Worker 
onRelease()127*c8dee2aaSAndroid Build Coastguard Worker void GrGLTexture::onRelease() {
128*c8dee2aaSAndroid Build Coastguard Worker     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
129*c8dee2aaSAndroid Build Coastguard Worker     ATRACE_ANDROID_FRAMEWORK_ALWAYS("Texture release(%u)", this->uniqueID().asUInt());
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker     if (fID) {
132*c8dee2aaSAndroid Build Coastguard Worker         if (GrBackendObjectOwnership::kBorrowed != fTextureIDOwnership) {
133*c8dee2aaSAndroid Build Coastguard Worker             GL_CALL(DeleteTextures(1, &fID));
134*c8dee2aaSAndroid Build Coastguard Worker         }
135*c8dee2aaSAndroid Build Coastguard Worker         fID = 0;
136*c8dee2aaSAndroid Build Coastguard Worker     }
137*c8dee2aaSAndroid Build Coastguard Worker     INHERITED::onRelease();
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker 
onAbandon()140*c8dee2aaSAndroid Build Coastguard Worker void GrGLTexture::onAbandon() {
141*c8dee2aaSAndroid Build Coastguard Worker     fID = 0;
142*c8dee2aaSAndroid Build Coastguard Worker     INHERITED::onAbandon();
143*c8dee2aaSAndroid Build Coastguard Worker }
144*c8dee2aaSAndroid Build Coastguard Worker 
getBackendTexture() const145*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture GrGLTexture::getBackendTexture() const {
146*c8dee2aaSAndroid Build Coastguard Worker     GrGLTextureInfo info;
147*c8dee2aaSAndroid Build Coastguard Worker     info.fTarget = target_from_texture_type(this->textureType());
148*c8dee2aaSAndroid Build Coastguard Worker     info.fID = fID;
149*c8dee2aaSAndroid Build Coastguard Worker     info.fFormat = GrGLFormatToEnum(fFormat);
150*c8dee2aaSAndroid Build Coastguard Worker     info.fProtected = skgpu::Protected(this->isProtected());
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker     return GrBackendTextures::MakeGL(
153*c8dee2aaSAndroid Build Coastguard Worker             this->width(), this->height(), this->mipmapped(), info, fParameters);
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker 
backendFormat() const156*c8dee2aaSAndroid Build Coastguard Worker GrBackendFormat GrGLTexture::backendFormat() const {
157*c8dee2aaSAndroid Build Coastguard Worker     return GrBackendFormats::MakeGL(GrGLFormatToEnum(fFormat),
158*c8dee2aaSAndroid Build Coastguard Worker                                     target_from_texture_type(this->textureType()));
159*c8dee2aaSAndroid Build Coastguard Worker }
160*c8dee2aaSAndroid Build Coastguard Worker 
MakeWrapped(GrGLGpu * gpu,GrMipmapStatus mipmapStatus,const Desc & desc,sk_sp<GrGLTextureParameters> parameters,GrWrapCacheable cacheable,GrIOType ioType,std::string_view label)161*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGLTexture> GrGLTexture::MakeWrapped(GrGLGpu* gpu,
162*c8dee2aaSAndroid Build Coastguard Worker                                             GrMipmapStatus mipmapStatus,
163*c8dee2aaSAndroid Build Coastguard Worker                                             const Desc& desc,
164*c8dee2aaSAndroid Build Coastguard Worker                                             sk_sp<GrGLTextureParameters> parameters,
165*c8dee2aaSAndroid Build Coastguard Worker                                             GrWrapCacheable cacheable,
166*c8dee2aaSAndroid Build Coastguard Worker                                             GrIOType ioType,
167*c8dee2aaSAndroid Build Coastguard Worker                                             std::string_view label) {
168*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<GrGLTexture>(new GrGLTexture(
169*c8dee2aaSAndroid Build Coastguard Worker             gpu, desc, mipmapStatus, std::move(parameters), cacheable, ioType, label));
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker 
onStealBackendTexture(GrBackendTexture * backendTexture,SkImages::BackendTextureReleaseProc * releaseProc)172*c8dee2aaSAndroid Build Coastguard Worker bool GrGLTexture::onStealBackendTexture(GrBackendTexture* backendTexture,
173*c8dee2aaSAndroid Build Coastguard Worker                                         SkImages::BackendTextureReleaseProc* releaseProc) {
174*c8dee2aaSAndroid Build Coastguard Worker     *backendTexture = this->getBackendTexture();
175*c8dee2aaSAndroid Build Coastguard Worker     // Set the release proc to a no-op function. GL doesn't require any special cleanup.
176*c8dee2aaSAndroid Build Coastguard Worker     *releaseProc = [](GrBackendTexture){};
177*c8dee2aaSAndroid Build Coastguard Worker 
178*c8dee2aaSAndroid Build Coastguard Worker     // It's important that we only abandon this texture's objects, not subclass objects such as
179*c8dee2aaSAndroid Build Coastguard Worker     // those held by GrGLTextureRenderTarget. Those objects are not being stolen and need to be
180*c8dee2aaSAndroid Build Coastguard Worker     // cleaned up by us.
181*c8dee2aaSAndroid Build Coastguard Worker     this->GrGLTexture::onAbandon();
182*c8dee2aaSAndroid Build Coastguard Worker     return true;
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker 
onSetLabel()185*c8dee2aaSAndroid Build Coastguard Worker void GrGLTexture::onSetLabel() {
186*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fID);
187*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fTextureIDOwnership == GrBackendObjectOwnership::kOwned);
188*c8dee2aaSAndroid Build Coastguard Worker     if (!this->getLabel().empty()) {
189*c8dee2aaSAndroid Build Coastguard Worker         const std::string label = "_Skia_" + this->getLabel();
190*c8dee2aaSAndroid Build Coastguard Worker         GrGLGpu* glGpu = static_cast<GrGLGpu*>(this->getGpu());
191*c8dee2aaSAndroid Build Coastguard Worker         if (glGpu->glCaps().debugSupport()) {
192*c8dee2aaSAndroid Build Coastguard Worker             GR_GL_CALL(glGpu->glInterface(), ObjectLabel(GR_GL_TEXTURE, fID, -1, label.c_str()));
193*c8dee2aaSAndroid Build Coastguard Worker         }
194*c8dee2aaSAndroid Build Coastguard Worker     }
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker 
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const197*c8dee2aaSAndroid Build Coastguard Worker void GrGLTexture::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
198*c8dee2aaSAndroid Build Coastguard Worker     // Don't check this->fRefsWrappedObjects, as we might be the base of a GrGLTextureRenderTarget
199*c8dee2aaSAndroid Build Coastguard Worker     // which is multiply inherited from both ourselves and a texture. In these cases, one part
200*c8dee2aaSAndroid Build Coastguard Worker     // (texture, rt) may be wrapped, while the other is owned by Skia.
201*c8dee2aaSAndroid Build Coastguard Worker     bool refsWrappedTextureObjects =
202*c8dee2aaSAndroid Build Coastguard Worker             this->fTextureIDOwnership == GrBackendObjectOwnership::kBorrowed;
203*c8dee2aaSAndroid Build Coastguard Worker     if (refsWrappedTextureObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
204*c8dee2aaSAndroid Build Coastguard Worker         return;
205*c8dee2aaSAndroid Build Coastguard Worker     }
206*c8dee2aaSAndroid Build Coastguard Worker 
207*c8dee2aaSAndroid Build Coastguard Worker     size_t size = GrSurface::ComputeSize(this->backendFormat(), this->dimensions(), 1,
208*c8dee2aaSAndroid Build Coastguard Worker                                          this->mipmapped());
209*c8dee2aaSAndroid Build Coastguard Worker 
210*c8dee2aaSAndroid Build Coastguard Worker     // Dump as skia/gpu_resources/resource_#/texture, to avoid conflicts in the
211*c8dee2aaSAndroid Build Coastguard Worker     // GrGLTextureRenderTarget case, where multiple things may dump to the same resource. This
212*c8dee2aaSAndroid Build Coastguard Worker     // has no downside in the normal case.
213*c8dee2aaSAndroid Build Coastguard Worker     SkString resourceName = this->getResourceName();
214*c8dee2aaSAndroid Build Coastguard Worker     resourceName.append("/texture");
215*c8dee2aaSAndroid Build Coastguard Worker 
216*c8dee2aaSAndroid Build Coastguard Worker     // As we are only dumping our texture memory (not any additional memory tracked by classes
217*c8dee2aaSAndroid Build Coastguard Worker     // which may inherit from us), specifically call GrGLTexture::gpuMemorySize to avoid
218*c8dee2aaSAndroid Build Coastguard Worker     // hitting an override.
219*c8dee2aaSAndroid Build Coastguard Worker     this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "Texture", size);
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker     SkString texture_id;
222*c8dee2aaSAndroid Build Coastguard Worker     texture_id.appendU32(this->textureID());
223*c8dee2aaSAndroid Build Coastguard Worker     traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_texture", texture_id.c_str());
224*c8dee2aaSAndroid Build Coastguard Worker }
225