xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gl/GrGLBackendSurface.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 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 #include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
8 
9 #include "include/core/SkRefCnt.h"
10 #include "include/core/SkTextureCompressionType.h"
11 #include "include/gpu/ganesh/GrBackendSurface.h"
12 #include "include/gpu/ganesh/GrTypes.h"
13 #include "include/gpu/ganesh/gl/GrGLTypes.h"
14 #include "include/private/base/SkAssert.h"
15 #include "include/private/base/SkDebug.h"
16 #include "include/private/gpu/ganesh/GrTypesPriv.h"
17 #include "src/gpu/ganesh/GrBackendSurfacePriv.h"
18 #include "src/gpu/ganesh/gl/GrGLBackendSurfacePriv.h"
19 #include "src/gpu/ganesh/gl/GrGLDefines.h"
20 #include "src/gpu/ganesh/gl/GrGLTypesPriv.h"
21 #include "src/gpu/ganesh/gl/GrGLUtil.h"
22 
23 #include <algorithm>
24 #include <cstddef>
25 #include <cstdint>
26 #include <string>
27 
28 class GrGLBackendFormatData final : public GrBackendFormatData {
29 public:
GrGLBackendFormatData(GrGLenum format)30     GrGLBackendFormatData(GrGLenum format) : fGLFormat(format) {}
31 
asEnum() const32     GrGLenum asEnum() const { return fGLFormat; }
33 
34 private:
compressionType() const35     SkTextureCompressionType compressionType() const override {
36         switch (GrGLFormatFromGLEnum(fGLFormat)) {
37             case GrGLFormat::kCOMPRESSED_ETC1_RGB8:
38             case GrGLFormat::kCOMPRESSED_RGB8_ETC2:
39                 return SkTextureCompressionType::kETC2_RGB8_UNORM;
40             case GrGLFormat::kCOMPRESSED_RGB8_BC1:
41                 return SkTextureCompressionType::kBC1_RGB8_UNORM;
42             case GrGLFormat::kCOMPRESSED_RGBA8_BC1:
43                 return SkTextureCompressionType::kBC1_RGBA8_UNORM;
44             default:
45                 return SkTextureCompressionType::kNone;
46         }
47     }
48 
bytesPerBlock() const49     size_t bytesPerBlock() const override {
50         return GrGLFormatBytesPerBlock(GrGLFormatFromGLEnum(fGLFormat));
51     }
52 
stencilBits() const53     int stencilBits() const override {
54         return GrGLFormatStencilBits(GrGLFormatFromGLEnum(fGLFormat));
55     }
56 
channelMask() const57     uint32_t channelMask() const override {
58         return GrGLFormatChannels(GrGLFormatFromGLEnum(fGLFormat));
59     }
60 
desc() const61     GrColorFormatDesc desc() const override {
62         return GrGLFormatDesc(GrGLFormatFromGLEnum(fGLFormat));
63     }
64 
equal(const GrBackendFormatData * that) const65     bool equal(const GrBackendFormatData* that) const override {
66         SkASSERT(!that || that->type() == GrBackendApi::kOpenGL);
67         if (auto otherGL = static_cast<const GrGLBackendFormatData*>(that)) {
68             return fGLFormat == otherGL->fGLFormat;
69         }
70         return false;
71     }
72 
toString() const73     std::string toString() const override {
74 #if defined(SK_DEBUG) || defined(GPU_TEST_UTILS)
75         return GrGLFormatToStr(fGLFormat);
76 #else
77         return "";
78 #endif
79     }
80 
copyTo(AnyFormatData & formatData) const81     void copyTo(AnyFormatData& formatData) const override {
82         formatData.emplace<GrGLBackendFormatData>(fGLFormat);
83     }
84 
85 #if defined(SK_DEBUG)
type() const86     GrBackendApi type() const override { return GrBackendApi::kOpenGL; }
87 #endif
88 
89     GrGLenum fGLFormat;  // the sized, internal format of the GL resource
90 };
91 
gl_target_to_gr_target(GrGLenum target)92 static GrTextureType gl_target_to_gr_target(GrGLenum target) {
93     switch (target) {
94         case GR_GL_TEXTURE_NONE:
95             return GrTextureType::kNone;
96         case GR_GL_TEXTURE_2D:
97             return GrTextureType::k2D;
98         case GR_GL_TEXTURE_RECTANGLE:
99             return GrTextureType::kRectangle;
100         case GR_GL_TEXTURE_EXTERNAL:
101             return GrTextureType::kExternal;
102         default:
103             SkUNREACHABLE;
104     }
105 }
106 
get_and_cast_data(const GrBackendFormat & format)107 static const GrGLBackendFormatData* get_and_cast_data(const GrBackendFormat& format) {
108     auto data = GrBackendSurfacePriv::GetBackendData(format);
109     SkASSERT(!data || data->type() == GrBackendApi::kOpenGL);
110     return static_cast<const GrGLBackendFormatData*>(data);
111 }
112 
113 namespace GrBackendFormats {
MakeGL(GrGLenum format,GrGLenum target)114 GrBackendFormat MakeGL(GrGLenum format, GrGLenum target) {
115     return GrBackendSurfacePriv::MakeGrBackendFormat(
116             gl_target_to_gr_target(target), GrBackendApi::kOpenGL, GrGLBackendFormatData(format));
117 }
118 
AsGLFormat(const GrBackendFormat & format)119 GrGLFormat AsGLFormat(const GrBackendFormat& format) {
120     if (format.isValid() && format.backend() == GrBackendApi::kOpenGL) {
121         const GrGLBackendFormatData* data = get_and_cast_data(format);
122         SkASSERT(data);
123         return GrGLFormatFromGLEnum(data->asEnum());
124     }
125     return GrGLFormat::kUnknown;
126 }
127 
AsGLFormatEnum(const GrBackendFormat & format)128 GrGLenum AsGLFormatEnum(const GrBackendFormat& format) {
129     if (format.isValid() && format.backend() == GrBackendApi::kOpenGL) {
130         const GrGLBackendFormatData* data = get_and_cast_data(format);
131         SkASSERT(data);
132         return data->asEnum();
133     }
134     return 0;
135 }
136 }  // namespace GrBackendFormats
137 
GrGLBackendTextureData(const GrGLTextureInfo & info,sk_sp<GrGLTextureParameters> params)138 GrGLBackendTextureData::GrGLBackendTextureData(const GrGLTextureInfo& info,
139                                                sk_sp<GrGLTextureParameters> params)
140         : fGLInfo(info, params) {}
141 
copyTo(AnyTextureData & textureData) const142 void GrGLBackendTextureData::copyTo(AnyTextureData& textureData) const {
143     textureData.emplace<GrGLBackendTextureData>(fGLInfo.info(), fGLInfo.refParameters());
144 }
145 
isProtected() const146 bool GrGLBackendTextureData::isProtected() const { return fGLInfo.isProtected(); }
147 
equal(const GrBackendTextureData * that) const148 bool GrGLBackendTextureData::equal(const GrBackendTextureData* that) const {
149     SkASSERT(!that || that->type() == GrBackendApi::kOpenGL);
150     if (auto otherGL = static_cast<const GrGLBackendTextureData*>(that)) {
151         return fGLInfo.info() == otherGL->fGLInfo.info();
152     }
153     return false;
154 }
155 
isSameTexture(const GrBackendTextureData * that) const156 bool GrGLBackendTextureData::isSameTexture(const GrBackendTextureData* that) const {
157     SkASSERT(!that || that->type() == GrBackendApi::kOpenGL);
158     if (auto otherGL = static_cast<const GrGLBackendTextureData*>(that)) {
159         return fGLInfo.info().fID == otherGL->fGLInfo.info().fID;
160     }
161     return false;
162 }
163 
getBackendFormat() const164 GrBackendFormat GrGLBackendTextureData::getBackendFormat() const {
165     return GrBackendFormats::MakeGL(fGLInfo.info().fFormat, fGLInfo.info().fTarget);
166 }
167 
get_and_cast_data(const GrBackendTexture & texture)168 static const GrGLBackendTextureData* get_and_cast_data(const GrBackendTexture& texture) {
169     auto data = GrBackendSurfacePriv::GetBackendData(texture);
170     SkASSERT(!data || data->type() == GrBackendApi::kOpenGL);
171     return static_cast<const GrGLBackendTextureData*>(data);
172 }
173 
get_and_cast_data(GrBackendTexture * texture)174 static GrGLBackendTextureData* get_and_cast_data(GrBackendTexture* texture) {
175     auto data = GrBackendSurfacePriv::GetBackendData(texture);
176     SkASSERT(!data || data->type() == GrBackendApi::kOpenGL);
177     return static_cast<GrGLBackendTextureData*>(data);
178 }
179 
180 namespace GrBackendTextures {
MakeGL(int width,int height,skgpu::Mipmapped mipped,const GrGLTextureInfo & glInfo,std::string_view label)181 GrBackendTexture MakeGL(int width,
182                         int height,
183                         skgpu::Mipmapped mipped,
184                         const GrGLTextureInfo& glInfo,
185                         std::string_view label) {
186     auto tex = GrBackendSurfacePriv::MakeGrBackendTexture(
187             width,
188             height,
189             label,
190             mipped,
191             GrBackendApi::kOpenGL,
192             gl_target_to_gr_target(glInfo.fTarget),
193             GrGLBackendTextureData(glInfo, sk_make_sp<GrGLTextureParameters>()));
194     // Make no assumptions about client's texture's parameters.
195     GLTextureParametersModified(&tex);
196     return tex;
197 }
198 
MakeGL(int width,int height,skgpu::Mipmapped mipped,const GrGLTextureInfo & glInfo,sk_sp<GrGLTextureParameters> params,std::string_view label)199 GrBackendTexture MakeGL(int width,
200                         int height,
201                         skgpu::Mipmapped mipped,
202                         const GrGLTextureInfo& glInfo,
203                         sk_sp<GrGLTextureParameters> params,
204                         std::string_view label) {
205     return GrBackendSurfacePriv::MakeGrBackendTexture(width,
206                                                       height,
207                                                       label,
208                                                       mipped,
209                                                       GrBackendApi::kOpenGL,
210                                                       gl_target_to_gr_target(glInfo.fTarget),
211                                                       GrGLBackendTextureData(glInfo, params));
212 }
213 
GetGLTextureInfo(const GrBackendTexture & tex,GrGLTextureInfo * outInfo)214 bool GetGLTextureInfo(const GrBackendTexture& tex, GrGLTextureInfo* outInfo) {
215     if (!tex.isValid() || tex.backend() != GrBackendApi::kOpenGL) {
216         return false;
217     }
218     const GrGLBackendTextureData* data = get_and_cast_data(tex);
219     SkASSERT(data);
220     *outInfo = data->info().info();
221     return true;
222 }
223 
GLTextureParametersModified(GrBackendTexture * tex)224 void GLTextureParametersModified(GrBackendTexture* tex) {
225     if (tex && tex->isValid() && tex->backend() == GrBackendApi::kOpenGL) {
226         GrGLBackendTextureData* data = get_and_cast_data(tex);
227         SkASSERT(data);
228         data->info().parameters()->invalidate();
229     }
230 }
231 }  // namespace GrBackendTextures
232 
233 class GrGLBackendRenderTargetData final : public GrBackendRenderTargetData {
234 public:
GrGLBackendRenderTargetData(GrGLFramebufferInfo info)235     GrGLBackendRenderTargetData(GrGLFramebufferInfo info) : fGLInfo(info) {}
236 
info() const237     GrGLFramebufferInfo info() const { return fGLInfo; }
238 
239 private:
getBackendFormat() const240     GrBackendFormat getBackendFormat() const override {
241         return GrBackendFormats::MakeGL(fGLInfo.fFormat, GR_GL_TEXTURE_NONE);
242     }
243 
isProtected() const244     bool isProtected() const override { return fGLInfo.isProtected(); }
245 
equal(const GrBackendRenderTargetData * that) const246     bool equal(const GrBackendRenderTargetData* that) const override {
247         SkASSERT(!that || that->type() == GrBackendApi::kOpenGL);
248         if (auto otherGL = static_cast<const GrGLBackendRenderTargetData*>(that)) {
249             return fGLInfo == otherGL->fGLInfo;
250         }
251         return false;
252     }
253 
copyTo(AnyRenderTargetData & rtData) const254     void copyTo(AnyRenderTargetData& rtData) const override {
255         rtData.emplace<GrGLBackendRenderTargetData>(fGLInfo);
256     }
257 
258 #if defined(SK_DEBUG)
type() const259     GrBackendApi type() const override { return GrBackendApi::kOpenGL; }
260 #endif
261 
262     GrGLFramebufferInfo fGLInfo;
263 };
264 
get_and_cast_data(const GrBackendRenderTarget & rt)265 static const GrGLBackendRenderTargetData* get_and_cast_data(const GrBackendRenderTarget& rt) {
266     auto data = GrBackendSurfacePriv::GetBackendData(rt);
267     SkASSERT(!data || data->type() == GrBackendApi::kOpenGL);
268     return static_cast<const GrGLBackendRenderTargetData*>(data);
269 }
270 
271 namespace GrBackendRenderTargets {
272 // The GrGLTextureInfo must have a valid fFormat. If wrapping in an SkSurface we require the
273 // stencil bits to be either 0, 8 or 16.
MakeGL(int width,int height,int sampleCnt,int stencilBits,const GrGLFramebufferInfo & glInfo)274 GrBackendRenderTarget MakeGL(
275         int width, int height, int sampleCnt, int stencilBits, const GrGLFramebufferInfo& glInfo) {
276     return GrBackendSurfacePriv::MakeGrBackendRenderTarget(width,
277                                                            height,
278                                                            std::max(1, sampleCnt),
279                                                            stencilBits,
280                                                            GrBackendApi::kOpenGL,
281                                                            /*framebufferOnly=*/false,
282                                                            GrGLBackendRenderTargetData(glInfo));
283 }
284 
GetGLFramebufferInfo(const GrBackendRenderTarget & rt,GrGLFramebufferInfo * outInfo)285 bool GetGLFramebufferInfo(const GrBackendRenderTarget& rt, GrGLFramebufferInfo* outInfo) {
286     if (!rt.isValid() || rt.backend() != GrBackendApi::kOpenGL) {
287         return false;
288     }
289     const GrGLBackendRenderTargetData* data = get_and_cast_data(rt);
290     SkASSERT(data);
291     *outInfo = data->info();
292     return true;
293 }
294 
295 }  // namespace GrBackendRenderTargets
296