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