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 case GrGLFormat::kCOMPRESSED_ASTC_RGBA8_4x4:
45 return SkTextureCompressionType::kASTC_RGBA8_4x4;
46 case GrGLFormat::kCOMPRESSED_ASTC_RGBA8_6x6:
47 return SkTextureCompressionType::kASTC_RGBA8_6x6;
48 case GrGLFormat::kCOMPRESSED_ASTC_RGBA8_8x8:
49 return SkTextureCompressionType::kASTC_RGBA8_8x8;
50 default:
51 return SkTextureCompressionType::kNone;
52 }
53 }
54
bytesPerBlock() const55 size_t bytesPerBlock() const override {
56 return GrGLFormatBytesPerBlock(GrGLFormatFromGLEnum(fGLFormat));
57 }
58
stencilBits() const59 int stencilBits() const override {
60 return GrGLFormatStencilBits(GrGLFormatFromGLEnum(fGLFormat));
61 }
62
channelMask() const63 uint32_t channelMask() const override {
64 return GrGLFormatChannels(GrGLFormatFromGLEnum(fGLFormat));
65 }
66
desc() const67 GrColorFormatDesc desc() const override {
68 return GrGLFormatDesc(GrGLFormatFromGLEnum(fGLFormat));
69 }
70
equal(const GrBackendFormatData * that) const71 bool equal(const GrBackendFormatData* that) const override {
72 SkASSERT(!that || that->type() == GrBackendApi::kOpenGL);
73 if (auto otherGL = static_cast<const GrGLBackendFormatData*>(that)) {
74 return fGLFormat == otherGL->fGLFormat;
75 }
76 return false;
77 }
78
toString() const79 std::string toString() const override {
80 #if defined(SK_DEBUG) || defined(GPU_TEST_UTILS)
81 return GrGLFormatToStr(fGLFormat);
82 #else
83 return "";
84 #endif
85 }
86
copyTo(AnyFormatData & formatData) const87 void copyTo(AnyFormatData& formatData) const override {
88 formatData.emplace<GrGLBackendFormatData>(fGLFormat);
89 }
90
91 #if defined(SK_DEBUG)
type() const92 GrBackendApi type() const override { return GrBackendApi::kOpenGL; }
93 #endif
94
95 GrGLenum fGLFormat; // the sized, internal format of the GL resource
96 };
97
gl_target_to_gr_target(GrGLenum target)98 static GrTextureType gl_target_to_gr_target(GrGLenum target) {
99 switch (target) {
100 case GR_GL_TEXTURE_NONE:
101 return GrTextureType::kNone;
102 case GR_GL_TEXTURE_2D:
103 return GrTextureType::k2D;
104 case GR_GL_TEXTURE_RECTANGLE:
105 return GrTextureType::kRectangle;
106 case GR_GL_TEXTURE_EXTERNAL:
107 return GrTextureType::kExternal;
108 default:
109 SkUNREACHABLE;
110 }
111 }
112
get_and_cast_data(const GrBackendFormat & format)113 static const GrGLBackendFormatData* get_and_cast_data(const GrBackendFormat& format) {
114 auto data = GrBackendSurfacePriv::GetBackendData(format);
115 SkASSERT(!data || data->type() == GrBackendApi::kOpenGL);
116 return static_cast<const GrGLBackendFormatData*>(data);
117 }
118
119 namespace GrBackendFormats {
MakeGL(GrGLenum format,GrGLenum target)120 GrBackendFormat MakeGL(GrGLenum format, GrGLenum target) {
121 return GrBackendSurfacePriv::MakeGrBackendFormat(
122 gl_target_to_gr_target(target), GrBackendApi::kOpenGL, GrGLBackendFormatData(format));
123 }
124
AsGLFormat(const GrBackendFormat & format)125 GrGLFormat AsGLFormat(const GrBackendFormat& format) {
126 if (format.isValid() && format.backend() == GrBackendApi::kOpenGL) {
127 const GrGLBackendFormatData* data = get_and_cast_data(format);
128 SkASSERT(data);
129 return GrGLFormatFromGLEnum(data->asEnum());
130 }
131 return GrGLFormat::kUnknown;
132 }
133
AsGLFormatEnum(const GrBackendFormat & format)134 GrGLenum AsGLFormatEnum(const GrBackendFormat& format) {
135 if (format.isValid() && format.backend() == GrBackendApi::kOpenGL) {
136 const GrGLBackendFormatData* data = get_and_cast_data(format);
137 SkASSERT(data);
138 return data->asEnum();
139 }
140 return 0;
141 }
142 } // namespace GrBackendFormats
143
GrGLBackendTextureData(const GrGLTextureInfo & info,sk_sp<GrGLTextureParameters> params)144 GrGLBackendTextureData::GrGLBackendTextureData(const GrGLTextureInfo& info,
145 sk_sp<GrGLTextureParameters> params)
146 : fGLInfo(info, params) {}
147
copyTo(AnyTextureData & textureData) const148 void GrGLBackendTextureData::copyTo(AnyTextureData& textureData) const {
149 textureData.emplace<GrGLBackendTextureData>(fGLInfo.info(), fGLInfo.refParameters());
150 }
151
isProtected() const152 bool GrGLBackendTextureData::isProtected() const { return fGLInfo.isProtected(); }
153
equal(const GrBackendTextureData * that) const154 bool GrGLBackendTextureData::equal(const GrBackendTextureData* that) const {
155 SkASSERT(!that || that->type() == GrBackendApi::kOpenGL);
156 if (auto otherGL = static_cast<const GrGLBackendTextureData*>(that)) {
157 return fGLInfo.info() == otherGL->fGLInfo.info();
158 }
159 return false;
160 }
161
isSameTexture(const GrBackendTextureData * that) const162 bool GrGLBackendTextureData::isSameTexture(const GrBackendTextureData* that) const {
163 SkASSERT(!that || that->type() == GrBackendApi::kOpenGL);
164 if (auto otherGL = static_cast<const GrGLBackendTextureData*>(that)) {
165 return fGLInfo.info().fID == otherGL->fGLInfo.info().fID;
166 }
167 return false;
168 }
169
getBackendFormat() const170 GrBackendFormat GrGLBackendTextureData::getBackendFormat() const {
171 return GrBackendFormats::MakeGL(fGLInfo.info().fFormat, fGLInfo.info().fTarget);
172 }
173
get_and_cast_data(const GrBackendTexture & texture)174 static const GrGLBackendTextureData* get_and_cast_data(const GrBackendTexture& texture) {
175 auto data = GrBackendSurfacePriv::GetBackendData(texture);
176 SkASSERT(!data || data->type() == GrBackendApi::kOpenGL);
177 return static_cast<const GrGLBackendTextureData*>(data);
178 }
179
get_and_cast_data(GrBackendTexture * texture)180 static GrGLBackendTextureData* get_and_cast_data(GrBackendTexture* texture) {
181 auto data = GrBackendSurfacePriv::GetBackendData(texture);
182 SkASSERT(!data || data->type() == GrBackendApi::kOpenGL);
183 return static_cast<GrGLBackendTextureData*>(data);
184 }
185
186 namespace GrBackendTextures {
MakeGL(int width,int height,skgpu::Mipmapped mipped,const GrGLTextureInfo & glInfo,std::string_view label)187 GrBackendTexture MakeGL(int width,
188 int height,
189 skgpu::Mipmapped mipped,
190 const GrGLTextureInfo& glInfo,
191 std::string_view label) {
192 auto tex = GrBackendSurfacePriv::MakeGrBackendTexture(
193 width,
194 height,
195 label,
196 mipped,
197 GrBackendApi::kOpenGL,
198 gl_target_to_gr_target(glInfo.fTarget),
199 GrGLBackendTextureData(glInfo, sk_make_sp<GrGLTextureParameters>()));
200 // Make no assumptions about client's texture's parameters.
201 GLTextureParametersModified(&tex);
202 return tex;
203 }
204
MakeGL(int width,int height,skgpu::Mipmapped mipped,const GrGLTextureInfo & glInfo,sk_sp<GrGLTextureParameters> params,std::string_view label)205 GrBackendTexture MakeGL(int width,
206 int height,
207 skgpu::Mipmapped mipped,
208 const GrGLTextureInfo& glInfo,
209 sk_sp<GrGLTextureParameters> params,
210 std::string_view label) {
211 return GrBackendSurfacePriv::MakeGrBackendTexture(width,
212 height,
213 label,
214 mipped,
215 GrBackendApi::kOpenGL,
216 gl_target_to_gr_target(glInfo.fTarget),
217 GrGLBackendTextureData(glInfo, params));
218 }
219
GetGLTextureInfo(const GrBackendTexture & tex,GrGLTextureInfo * outInfo)220 bool GetGLTextureInfo(const GrBackendTexture& tex, GrGLTextureInfo* outInfo) {
221 if (!tex.isValid() || tex.backend() != GrBackendApi::kOpenGL) {
222 return false;
223 }
224 const GrGLBackendTextureData* data = get_and_cast_data(tex);
225 SkASSERT(data);
226 *outInfo = data->info().info();
227 return true;
228 }
229
GLTextureParametersModified(GrBackendTexture * tex)230 void GLTextureParametersModified(GrBackendTexture* tex) {
231 if (tex && tex->isValid() && tex->backend() == GrBackendApi::kOpenGL) {
232 GrGLBackendTextureData* data = get_and_cast_data(tex);
233 SkASSERT(data);
234 data->info().parameters()->invalidate();
235 }
236 }
237 } // namespace GrBackendTextures
238
239 class GrGLBackendRenderTargetData final : public GrBackendRenderTargetData {
240 public:
GrGLBackendRenderTargetData(GrGLFramebufferInfo info)241 GrGLBackendRenderTargetData(GrGLFramebufferInfo info) : fGLInfo(info) {}
242
info() const243 GrGLFramebufferInfo info() const { return fGLInfo; }
244
245 private:
getBackendFormat() const246 GrBackendFormat getBackendFormat() const override {
247 return GrBackendFormats::MakeGL(fGLInfo.fFormat, GR_GL_TEXTURE_NONE);
248 }
249
isProtected() const250 bool isProtected() const override { return fGLInfo.isProtected(); }
251
equal(const GrBackendRenderTargetData * that) const252 bool equal(const GrBackendRenderTargetData* that) const override {
253 SkASSERT(!that || that->type() == GrBackendApi::kOpenGL);
254 if (auto otherGL = static_cast<const GrGLBackendRenderTargetData*>(that)) {
255 return fGLInfo == otherGL->fGLInfo;
256 }
257 return false;
258 }
259
copyTo(AnyRenderTargetData & rtData) const260 void copyTo(AnyRenderTargetData& rtData) const override {
261 rtData.emplace<GrGLBackendRenderTargetData>(fGLInfo);
262 }
263
264 #if defined(SK_DEBUG)
type() const265 GrBackendApi type() const override { return GrBackendApi::kOpenGL; }
266 #endif
267
268 GrGLFramebufferInfo fGLInfo;
269 };
270
get_and_cast_data(const GrBackendRenderTarget & rt)271 static const GrGLBackendRenderTargetData* get_and_cast_data(const GrBackendRenderTarget& rt) {
272 auto data = GrBackendSurfacePriv::GetBackendData(rt);
273 SkASSERT(!data || data->type() == GrBackendApi::kOpenGL);
274 return static_cast<const GrGLBackendRenderTargetData*>(data);
275 }
276
277 namespace GrBackendRenderTargets {
278 // The GrGLTextureInfo must have a valid fFormat. If wrapping in an SkSurface we require the
279 // stencil bits to be either 0, 8 or 16.
MakeGL(int width,int height,int sampleCnt,int stencilBits,const GrGLFramebufferInfo & glInfo)280 GrBackendRenderTarget MakeGL(
281 int width, int height, int sampleCnt, int stencilBits, const GrGLFramebufferInfo& glInfo) {
282 return GrBackendSurfacePriv::MakeGrBackendRenderTarget(width,
283 height,
284 std::max(1, sampleCnt),
285 stencilBits,
286 GrBackendApi::kOpenGL,
287 /*framebufferOnly=*/false,
288 GrGLBackendRenderTargetData(glInfo));
289 }
290
GetGLFramebufferInfo(const GrBackendRenderTarget & rt,GrGLFramebufferInfo * outInfo)291 bool GetGLFramebufferInfo(const GrBackendRenderTarget& rt, GrGLFramebufferInfo* outInfo) {
292 if (!rt.isValid() || rt.backend() != GrBackendApi::kOpenGL) {
293 return false;
294 }
295 const GrGLBackendRenderTargetData* data = get_and_cast_data(rt);
296 SkASSERT(data);
297 *outInfo = data->info();
298 return true;
299 }
300
301 } // namespace GrBackendRenderTargets
302