Serenity Operating System
1/*
2 * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibGL/Image.h>
8
9namespace GL {
10
11ErrorOr<GPU::PixelType> get_validated_pixel_type(GLenum target, GLenum internal_format, GLenum format, GLenum type)
12{
13 // We accept GL_NONE as target for non-texture related calls (such as `glDrawPixels`)
14 if (target != GL_NONE
15 && target != GL_TEXTURE_1D
16 && target != GL_TEXTURE_2D
17 && target != GL_TEXTURE_3D
18 && target != GL_TEXTURE_1D_ARRAY
19 && target != GL_TEXTURE_2D_ARRAY
20 && target != GL_TEXTURE_CUBE_MAP
21 && target != GL_PROXY_TEXTURE_1D
22 && target != GL_PROXY_TEXTURE_2D
23 && target != GL_PROXY_TEXTURE_3D)
24 return Error::from_errno(GL_INVALID_ENUM);
25
26 // Internal format can be a number between 1 and 4. Symbolic formats were only added with EXT_texture, promoted to core in OpenGL 1.1
27 if (internal_format == 1)
28 internal_format = GL_ALPHA;
29 else if (internal_format == 2)
30 internal_format = GL_LUMINANCE_ALPHA;
31 else if (internal_format == 3)
32 internal_format = GL_RGB;
33 else if (internal_format == 4)
34 internal_format = GL_RGBA;
35
36 if (internal_format != GL_NONE
37 && internal_format != GL_ALPHA
38 && internal_format != GL_ALPHA4
39 && internal_format != GL_ALPHA8
40 && internal_format != GL_ALPHA12
41 && internal_format != GL_ALPHA16
42 && internal_format != GL_COMPRESSED_ALPHA
43 && internal_format != GL_COMPRESSED_LUMINANCE
44 && internal_format != GL_COMPRESSED_LUMINANCE_ALPHA
45 && internal_format != GL_COMPRESSED_INTENSITY
46 && internal_format != GL_COMPRESSED_RGB
47 && internal_format != GL_COMPRESSED_RGBA
48 && internal_format != GL_DEPTH_COMPONENT
49 && internal_format != GL_DEPTH_COMPONENT16
50 && internal_format != GL_DEPTH_COMPONENT24
51 && internal_format != GL_DEPTH_COMPONENT32
52 && internal_format != GL_DEPTH_STENCIL
53 && internal_format != GL_LUMINANCE
54 && internal_format != GL_LUMINANCE4
55 && internal_format != GL_LUMINANCE8
56 && internal_format != GL_LUMINANCE12
57 && internal_format != GL_LUMINANCE16
58 && internal_format != GL_LUMINANCE_ALPHA
59 && internal_format != GL_LUMINANCE4_ALPHA4
60 && internal_format != GL_LUMINANCE6_ALPHA2
61 && internal_format != GL_LUMINANCE8_ALPHA8
62 && internal_format != GL_LUMINANCE12_ALPHA4
63 && internal_format != GL_LUMINANCE12_ALPHA12
64 && internal_format != GL_LUMINANCE16_ALPHA16
65 && internal_format != GL_INTENSITY
66 && internal_format != GL_INTENSITY4
67 && internal_format != GL_INTENSITY8
68 && internal_format != GL_INTENSITY12
69 && internal_format != GL_INTENSITY16
70 && internal_format != GL_R3_G3_B2
71 && internal_format != GL_RED
72 && internal_format != GL_RG
73 && internal_format != GL_RGB
74 && internal_format != GL_RGB4
75 && internal_format != GL_RGB5
76 && internal_format != GL_RGB8
77 && internal_format != GL_RGB10
78 && internal_format != GL_RGB12
79 && internal_format != GL_RGB16
80 && internal_format != GL_RGBA
81 && internal_format != GL_RGBA2
82 && internal_format != GL_RGBA4
83 && internal_format != GL_RGB5_A1
84 && internal_format != GL_RGBA8
85 && internal_format != GL_RGB10_A2
86 && internal_format != GL_RGBA12
87 && internal_format != GL_RGBA16
88 && internal_format != GL_SLUMINANCE
89 && internal_format != GL_SLUMINANCE8
90 && internal_format != GL_SLUMINANCE_ALPHA
91 && internal_format != GL_SLUMINANCE8_ALPHA8
92 && internal_format != GL_SRGB
93 && internal_format != GL_SRGB8
94 && internal_format != GL_SRGB_ALPHA
95 && internal_format != GL_SRGB8_ALPHA8)
96 return Error::from_errno(GL_INVALID_ENUM);
97
98 if (format != GL_NONE
99 && (format < GL_COLOR_INDEX || format > GL_LUMINANCE_ALPHA)
100 && format != GL_BGR
101 && format != GL_BGRA)
102 return Error::from_errno(GL_INVALID_ENUM);
103
104 if (type != GL_NONE
105 && type != GL_BITMAP
106 && (type < GL_BYTE || type > GL_FLOAT)
107 && type != GL_HALF_FLOAT
108 && (type < GL_UNSIGNED_BYTE_3_3_2 || type > GL_UNSIGNED_INT_10_10_10_2)
109 && (type < GL_UNSIGNED_BYTE_2_3_3_REV || type > GL_UNSIGNED_INT_2_10_10_10_REV))
110 return Error::from_errno(GL_INVALID_ENUM);
111
112 if (type == GL_BITMAP && format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX)
113 return Error::from_errno(GL_INVALID_ENUM);
114
115 if (format != GL_RGB && (type == GL_UNSIGNED_BYTE_3_3_2 || type == GL_UNSIGNED_BYTE_2_3_3_REV || type == GL_UNSIGNED_SHORT_5_6_5 || type == GL_UNSIGNED_SHORT_5_6_5_REV))
116 return Error::from_errno(GL_INVALID_OPERATION);
117
118 if ((type == GL_UNSIGNED_SHORT_4_4_4_4
119 || type == GL_UNSIGNED_SHORT_4_4_4_4_REV
120 || type == GL_UNSIGNED_SHORT_5_5_5_1
121 || type == GL_UNSIGNED_SHORT_1_5_5_5_REV
122 || type == GL_UNSIGNED_INT_8_8_8_8
123 || type == GL_UNSIGNED_INT_8_8_8_8_REV
124 || type == GL_UNSIGNED_INT_10_10_10_2
125 || type == GL_UNSIGNED_INT_2_10_10_10_REV)
126 && format != GL_RGBA
127 && format != GL_BGRA)
128 return Error::from_errno(GL_INVALID_OPERATION);
129
130 if (internal_format != GL_NONE) {
131 auto const internal_format_is_depth = internal_format == GL_DEPTH_COMPONENT
132 || internal_format == GL_DEPTH_COMPONENT16
133 || internal_format == GL_DEPTH_COMPONENT24
134 || internal_format == GL_DEPTH_COMPONENT32;
135
136 if ((target != GL_TEXTURE_2D && target != GL_PROXY_TEXTURE_2D && internal_format_is_depth)
137 || (format == GL_DEPTH_COMPONENT && !internal_format_is_depth)
138 || (format != GL_DEPTH_COMPONENT && internal_format_is_depth))
139 return Error::from_errno(GL_INVALID_OPERATION);
140 }
141
142 return get_format_specification(format, type);
143}
144
145GPU::PixelType get_format_specification(GLenum format, GLenum type)
146{
147 auto get_format = [](GLenum format) -> GPU::PixelFormat {
148 switch (format) {
149 case GL_ALPHA:
150 return GPU::PixelFormat::Alpha;
151 case GL_BGR:
152 return GPU::PixelFormat::BGR;
153 case GL_BGRA:
154 return GPU::PixelFormat::BGRA;
155 case GL_BLUE:
156 return GPU::PixelFormat::Blue;
157 case GL_COLOR_INDEX:
158 return GPU::PixelFormat::ColorIndex;
159 case GL_DEPTH_COMPONENT:
160 return GPU::PixelFormat::DepthComponent;
161 case GL_GREEN:
162 return GPU::PixelFormat::Green;
163 case GL_LUMINANCE:
164 return GPU::PixelFormat::Luminance;
165 case GL_LUMINANCE_ALPHA:
166 return GPU::PixelFormat::LuminanceAlpha;
167 case GL_RED:
168 return GPU::PixelFormat::Red;
169 case GL_RGB:
170 return GPU::PixelFormat::RGB;
171 case GL_RGBA:
172 return GPU::PixelFormat::RGBA;
173 case GL_STENCIL_INDEX:
174 return GPU::PixelFormat::StencilIndex;
175 }
176 VERIFY_NOT_REACHED();
177 };
178 auto pixel_format = get_format(format);
179
180 switch (type) {
181 case GL_BITMAP:
182 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::Bitmap, GPU::ComponentsOrder::Normal };
183 case GL_BYTE:
184 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::Byte, GPU::ComponentsOrder::Normal };
185 case GL_FLOAT:
186 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::Float, GPU::ComponentsOrder::Normal };
187 case GL_HALF_FLOAT:
188 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::HalfFloat, GPU::ComponentsOrder::Normal };
189 case GL_INT:
190 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::Int, GPU::ComponentsOrder::Normal };
191 case GL_SHORT:
192 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::Short, GPU::ComponentsOrder::Normal };
193 case GL_UNSIGNED_BYTE:
194 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::UnsignedByte, GPU::ComponentsOrder::Normal };
195 case GL_UNSIGNED_BYTE_2_3_3_REV:
196 return { pixel_format, GPU::PixelComponentBits::B2_3_3, GPU::PixelDataType::UnsignedByte, GPU::ComponentsOrder::Reversed };
197 case GL_UNSIGNED_BYTE_3_3_2:
198 return { pixel_format, GPU::PixelComponentBits::B3_3_2, GPU::PixelDataType::UnsignedByte, GPU::ComponentsOrder::Normal };
199 case GL_UNSIGNED_INT:
200 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::UnsignedInt, GPU::ComponentsOrder::Normal };
201 case GL_UNSIGNED_INT_2_10_10_10_REV:
202 return { pixel_format, GPU::PixelComponentBits::B2_10_10_10, GPU::PixelDataType::UnsignedInt, GPU::ComponentsOrder::Reversed };
203 case GL_UNSIGNED_INT_8_8_8_8:
204 return { pixel_format, GPU::PixelComponentBits::B8_8_8_8, GPU::PixelDataType::UnsignedInt, GPU::ComponentsOrder::Normal };
205 case GL_UNSIGNED_INT_8_8_8_8_REV:
206 return { pixel_format, GPU::PixelComponentBits::B8_8_8_8, GPU::PixelDataType::UnsignedInt, GPU::ComponentsOrder::Reversed };
207 case GL_UNSIGNED_INT_10_10_10_2:
208 return { pixel_format, GPU::PixelComponentBits::B10_10_10_2, GPU::PixelDataType::UnsignedInt, GPU::ComponentsOrder::Normal };
209 case GL_UNSIGNED_SHORT:
210 return { pixel_format, GPU::PixelComponentBits::AllBits, GPU::PixelDataType::UnsignedShort, GPU::ComponentsOrder::Normal };
211 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
212 return { pixel_format, GPU::PixelComponentBits::B1_5_5_5, GPU::PixelDataType::UnsignedShort, GPU::ComponentsOrder::Reversed };
213 case GL_UNSIGNED_SHORT_4_4_4_4:
214 return { pixel_format, GPU::PixelComponentBits::B4_4_4_4, GPU::PixelDataType::UnsignedShort, GPU::ComponentsOrder::Normal };
215 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
216 return { pixel_format, GPU::PixelComponentBits::B4_4_4_4, GPU::PixelDataType::UnsignedShort, GPU::ComponentsOrder::Reversed };
217 case GL_UNSIGNED_SHORT_5_6_5:
218 return { pixel_format, GPU::PixelComponentBits::B5_6_5, GPU::PixelDataType::UnsignedShort, GPU::ComponentsOrder::Normal };
219 case GL_UNSIGNED_SHORT_5_6_5_REV:
220 return { pixel_format, GPU::PixelComponentBits::B5_6_5, GPU::PixelDataType::UnsignedShort, GPU::ComponentsOrder::Reversed };
221 case GL_UNSIGNED_SHORT_5_5_5_1:
222 return { pixel_format, GPU::PixelComponentBits::B5_5_5_1, GPU::PixelDataType::UnsignedShort, GPU::ComponentsOrder::Normal };
223 }
224 VERIFY_NOT_REACHED();
225}
226
227GPU::PixelFormat pixel_format_for_internal_format(GLenum internal_format)
228{
229 // FIXME: add support for all the SRGB formats
230
231 // Numbers 1-4 are supported deprecated values
232 switch (internal_format) {
233 case 1:
234 case GL_ALPHA:
235 case GL_ALPHA4:
236 case GL_ALPHA8:
237 case GL_ALPHA12:
238 case GL_ALPHA16:
239 case GL_COMPRESSED_ALPHA:
240 return GPU::PixelFormat::Alpha;
241 case GL_DEPTH_COMPONENT:
242 case GL_DEPTH_COMPONENT16:
243 case GL_DEPTH_COMPONENT24:
244 case GL_DEPTH_COMPONENT32:
245 return GPU::PixelFormat::DepthComponent;
246 case GL_INTENSITY:
247 case GL_INTENSITY4:
248 case GL_INTENSITY8:
249 case GL_INTENSITY12:
250 case GL_INTENSITY16:
251 case GL_COMPRESSED_INTENSITY:
252 return GPU::PixelFormat::Intensity;
253 case GL_LUMINANCE:
254 case GL_LUMINANCE4:
255 case GL_LUMINANCE8:
256 case GL_LUMINANCE12:
257 case GL_LUMINANCE16:
258 case GL_COMPRESSED_LUMINANCE:
259 return GPU::PixelFormat::Luminance;
260 case 2:
261 case GL_LUMINANCE_ALPHA:
262 case GL_LUMINANCE4_ALPHA4:
263 case GL_LUMINANCE6_ALPHA2:
264 case GL_LUMINANCE8_ALPHA8:
265 case GL_LUMINANCE12_ALPHA4:
266 case GL_LUMINANCE12_ALPHA12:
267 case GL_LUMINANCE16_ALPHA16:
268 return GPU::PixelFormat::LuminanceAlpha;
269 case 3:
270 case GL_RGB:
271 case GL_R3_G3_B2:
272 case GL_RGB4:
273 case GL_RGB5:
274 case GL_RGB8:
275 case GL_RGB10:
276 case GL_RGB12:
277 case GL_RGB16:
278 case GL_COMPRESSED_RGB:
279 return GPU::PixelFormat::RGB;
280 case 4:
281 case GL_RGBA:
282 case GL_RGBA2:
283 case GL_RGBA4:
284 case GL_RGBA8:
285 case GL_RGB10_A2:
286 case GL_RGBA12:
287 case GL_RGBA16:
288 case GL_COMPRESSED_RGBA:
289 return GPU::PixelFormat::RGBA;
290 }
291 VERIFY_NOT_REACHED();
292}
293
294}