1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef WEBGL_STRONG_TYPES_H_
7 #define WEBGL_STRONG_TYPES_H_
12 #include "mozilla/ArrayUtils.h"
13 #include "mozilla/Assertions.h"
14 #include "mozilla/Attributes.h"
19 * To create a new type from a set of GLenums do the following:
21 * STRONG_GLENUM_BEGIN(TypeName)
22 * STRONG_GLENUM_VALUE(ENUM1),
23 * STRONG_GLENUM_VALUE(ENUM2),
27 * where TypeName is the name you want to give the type. Now simply use TypeName
28 * instead of GLenum. The enum values must be given without GL_ prefix.
34 * Boolean operators (==, !=) are provided in an effort to prevent some mistakes
35 * when using constants. For example we want to make sure that GL_ENUM_X is
36 * a valid value for the type in code like:
38 * if (myNewType == STRONG_GLENUM_VALUE(SOME_ENUM))
41 * The operators will assert that STRONG_GLENUM_VALUE(SOME_ENUM) is a value that
46 * A get() method is provided to allow access to the underlying GLenum. This
47 * method should ideally only be called when passing parameters to the gl->fXXXX
48 * functions, and be used very minimally everywhere else.
50 * Definitely XXX - DO NOT DO - XXX:
52 * if (myNewType.get() == STRONG_GLENUM_VALUE(SOME_ENUM))
55 * As that undermines the debug checks that were implemented in the ==, and !=
56 * operators. If you see code like this it should be treated with suspicion.
61 * This macro is the first step in an effort to make the WebGL code safer.
62 * Many of the different functions take GLenum as their parameter which leads
63 * to bugs because of subtle differences in the enums purpose. For example there
64 * are two types of 'texture targets'. One is the texture binding locations:
69 * Yet, this is not the same as texture image targets:
72 * GL_TEXTURE_CUBE_MAP_POSITIVE_X
73 * GL_TEXTURE_CUBE_MAP_NEGATIVE_X
74 * GL_TEXTURE_CUBE_MAP_POSITIVE_Y
77 * This subtle distinction has already led to many bugs in the texture code
78 * because of invalid assumptions about what type goes where. The macro below
79 * is an attempt at fixing this by providing a small wrapper around GLenum that
80 * validates its values.
82 * Comparison between STRONG_GLENUM's vs. enum classes
83 * ===================================================
85 * The present STRONG_GLENUM's differ from ordinary enum classes
86 * in that they assert at runtime that their values are legal, and in that they
87 * allow implicit conversion from integers to STRONG_GLENUM's but disallow
88 * implicit conversion from STRONG_GLENUM's to integers (enum classes are the
91 * When to use GLenum's vs. STRONG_GLENUM's vs. enum classes
92 * =========================================================
95 * * For unchecked GLenum constants, such as WebGL method parameters that
96 * haven't been validated yet, use GLenum.
97 * * For already-validated GLenum constants, use STRONG_GLENUM's.
98 * * For custom constants that aren't GL enum values, use enum classes.
101 template <typename Details
>
102 class StrongGLenum final
{
104 static const GLenum NonexistantGLenum
= 0xdeaddead;
108 static void AssertOnceThatEnumValuesAreSorted() {
110 static bool alreadyChecked
= false;
111 if (alreadyChecked
) {
114 for (size_t i
= 1; i
< Details::valuesCount(); i
++) {
115 MOZ_ASSERT(Details::values()[i
] > Details::values()[i
- 1],
116 "GLenum values should be sorted in ascending order");
118 alreadyChecked
= true;
123 StrongGLenum() : mValue(NonexistantGLenum
) {
124 AssertOnceThatEnumValuesAreSorted();
127 MOZ_IMPLICIT
StrongGLenum(GLenum value
) : mValue(value
) {
128 AssertOnceThatEnumValuesAreSorted();
129 MOZ_ASSERT(IsValueLegal(mValue
));
133 MOZ_ASSERT(mValue
!= NonexistantGLenum
);
137 bool operator==(const StrongGLenum
& other
) const {
138 return get() == other
.get();
141 bool operator!=(const StrongGLenum
& other
) const {
142 return get() != other
.get();
145 bool operator<=(const StrongGLenum
& other
) const {
146 return get() <= other
.get();
149 bool operator>=(const StrongGLenum
& other
) const {
150 return get() >= other
.get();
153 explicit operator bool() const { return bool(get()); }
155 static bool IsValueLegal(GLenum value
) {
156 if (value
> UINT16_MAX
) {
159 return std::binary_search(Details::values(),
160 Details::values() + Details::valuesCount(),
165 template <typename Details
>
166 bool operator==(GLenum a
, StrongGLenum
<Details
> b
) {
170 template <typename Details
>
171 bool operator!=(GLenum a
, StrongGLenum
<Details
> b
) {
175 template <typename Details
>
176 bool operator==(StrongGLenum
<Details
> a
, GLenum b
) {
180 template <typename Details
>
181 bool operator!=(StrongGLenum
<Details
> a
, GLenum b
) {
185 #define STRONG_GLENUM_BEGIN(NAME) const uint16_t NAME##Values[] = {
186 #define STRONG_GLENUM_VALUE(VALUE) LOCAL_GL_##VALUE
188 #define STRONG_GLENUM_END(NAME) \
191 struct NAME##Details { \
192 static size_t valuesCount() { return MOZ_ARRAY_LENGTH(NAME##Values); } \
193 static const uint16_t* values() { return NAME##Values; } \
195 typedef StrongGLenum<NAME##Details> NAME;
197 ////////////////////////////////////////////////////////////////////////////////
200 STRONG_GLENUM_BEGIN(TexImageTarget
)
201 STRONG_GLENUM_VALUE(NONE
), STRONG_GLENUM_VALUE(TEXTURE_2D
),
202 STRONG_GLENUM_VALUE(TEXTURE_3D
),
203 STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_POSITIVE_X
),
204 STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_X
),
205 STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_POSITIVE_Y
),
206 STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_Y
),
207 STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_POSITIVE_Z
),
208 STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_Z
),
209 STRONG_GLENUM_VALUE(TEXTURE_2D_ARRAY
),
210 STRONG_GLENUM_END(TexImageTarget
)
212 STRONG_GLENUM_BEGIN(TexTarget
) STRONG_GLENUM_VALUE(NONE
),
213 STRONG_GLENUM_VALUE(TEXTURE_2D
), STRONG_GLENUM_VALUE(TEXTURE_3D
),
214 STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP
),
215 STRONG_GLENUM_VALUE(TEXTURE_2D_ARRAY
),
216 STRONG_GLENUM_END(TexTarget
)
218 STRONG_GLENUM_BEGIN(TexType
) STRONG_GLENUM_VALUE(NONE
),
219 STRONG_GLENUM_VALUE(BYTE
), STRONG_GLENUM_VALUE(UNSIGNED_BYTE
),
220 STRONG_GLENUM_VALUE(SHORT
), STRONG_GLENUM_VALUE(UNSIGNED_SHORT
),
221 STRONG_GLENUM_VALUE(INT
), STRONG_GLENUM_VALUE(UNSIGNED_INT
),
222 STRONG_GLENUM_VALUE(FLOAT
), STRONG_GLENUM_VALUE(HALF_FLOAT
),
223 STRONG_GLENUM_VALUE(UNSIGNED_SHORT_4_4_4_4
),
224 STRONG_GLENUM_VALUE(UNSIGNED_SHORT_5_5_5_1
),
225 STRONG_GLENUM_VALUE(UNSIGNED_SHORT_5_6_5
),
226 STRONG_GLENUM_VALUE(UNSIGNED_INT_2_10_10_10_REV
),
227 STRONG_GLENUM_VALUE(UNSIGNED_INT_24_8
),
228 STRONG_GLENUM_VALUE(UNSIGNED_INT_10F_11F_11F_REV
),
229 STRONG_GLENUM_VALUE(UNSIGNED_INT_5_9_9_9_REV
),
230 STRONG_GLENUM_VALUE(HALF_FLOAT_OES
),
231 STRONG_GLENUM_VALUE(FLOAT_32_UNSIGNED_INT_24_8_REV
),
232 STRONG_GLENUM_END(TexType
)
234 STRONG_GLENUM_BEGIN(TexMinFilter
) STRONG_GLENUM_VALUE(NEAREST
),
235 STRONG_GLENUM_VALUE(LINEAR
), STRONG_GLENUM_VALUE(NEAREST_MIPMAP_NEAREST
),
236 STRONG_GLENUM_VALUE(LINEAR_MIPMAP_NEAREST
),
237 STRONG_GLENUM_VALUE(NEAREST_MIPMAP_LINEAR
),
238 STRONG_GLENUM_VALUE(LINEAR_MIPMAP_LINEAR
),
239 STRONG_GLENUM_END(TexMinFilter
)
241 STRONG_GLENUM_BEGIN(TexMagFilter
) STRONG_GLENUM_VALUE(NEAREST
),
242 STRONG_GLENUM_VALUE(LINEAR
),
243 STRONG_GLENUM_END(TexMagFilter
)
245 STRONG_GLENUM_BEGIN(TexWrap
) STRONG_GLENUM_VALUE(REPEAT
),
246 STRONG_GLENUM_VALUE(CLAMP_TO_EDGE
), STRONG_GLENUM_VALUE(MIRRORED_REPEAT
),
247 STRONG_GLENUM_END(TexWrap
)
249 STRONG_GLENUM_BEGIN(TexCompareMode
) STRONG_GLENUM_VALUE(NONE
),
250 STRONG_GLENUM_VALUE(COMPARE_REF_TO_TEXTURE
),
251 STRONG_GLENUM_END(TexCompareMode
)
253 STRONG_GLENUM_BEGIN(TexCompareFunc
) STRONG_GLENUM_VALUE(NEVER
),
254 STRONG_GLENUM_VALUE(LESS
), STRONG_GLENUM_VALUE(EQUAL
),
255 STRONG_GLENUM_VALUE(LEQUAL
), STRONG_GLENUM_VALUE(GREATER
),
256 STRONG_GLENUM_VALUE(NOTEQUAL
), STRONG_GLENUM_VALUE(GEQUAL
),
257 STRONG_GLENUM_VALUE(ALWAYS
),
258 STRONG_GLENUM_END(TexCompareFunc
)
260 STRONG_GLENUM_BEGIN(TexFormat
) STRONG_GLENUM_VALUE(NONE
), // 0x0000
261 STRONG_GLENUM_VALUE(DEPTH_COMPONENT
), // 0x1902
262 STRONG_GLENUM_VALUE(RED
), // 0x1903
263 STRONG_GLENUM_VALUE(ALPHA
), // 0x1906
264 STRONG_GLENUM_VALUE(RGB
), // 0x1907
265 STRONG_GLENUM_VALUE(RGBA
), // 0x1908
266 STRONG_GLENUM_VALUE(LUMINANCE
), // 0x1909
267 STRONG_GLENUM_VALUE(LUMINANCE_ALPHA
), // 0x190A
268 STRONG_GLENUM_VALUE(RG
), // 0x8227
269 STRONG_GLENUM_VALUE(RG_INTEGER
), // 0x8228
270 STRONG_GLENUM_VALUE(DEPTH_STENCIL
), // 0x84F9
271 STRONG_GLENUM_VALUE(SRGB
), // 0x8C40
272 STRONG_GLENUM_VALUE(SRGB_ALPHA
), // 0x8C42
273 STRONG_GLENUM_VALUE(RED_INTEGER
), // 0x8D94
274 STRONG_GLENUM_VALUE(RGB_INTEGER
), // 0x8D98
275 STRONG_GLENUM_VALUE(RGBA_INTEGER
), // 0x8D99
276 STRONG_GLENUM_END(TexFormat
)
278 STRONG_GLENUM_BEGIN(TexInternalFormat
) STRONG_GLENUM_VALUE(NONE
),
279 STRONG_GLENUM_VALUE(DEPTH_COMPONENT
), STRONG_GLENUM_VALUE(RED
),
280 STRONG_GLENUM_VALUE(ALPHA
), STRONG_GLENUM_VALUE(RGB
),
281 STRONG_GLENUM_VALUE(RGBA
), STRONG_GLENUM_VALUE(LUMINANCE
),
282 STRONG_GLENUM_VALUE(LUMINANCE_ALPHA
), STRONG_GLENUM_VALUE(ALPHA8
),
283 STRONG_GLENUM_VALUE(LUMINANCE8
), STRONG_GLENUM_VALUE(LUMINANCE8_ALPHA8
),
284 STRONG_GLENUM_VALUE(RGB8
), STRONG_GLENUM_VALUE(RGBA4
),
285 STRONG_GLENUM_VALUE(RGB5_A1
), STRONG_GLENUM_VALUE(RGBA8
),
286 STRONG_GLENUM_VALUE(RGB10_A2
), STRONG_GLENUM_VALUE(DEPTH_COMPONENT16
),
287 STRONG_GLENUM_VALUE(DEPTH_COMPONENT24
), STRONG_GLENUM_VALUE(RG
),
288 STRONG_GLENUM_VALUE(RG_INTEGER
), STRONG_GLENUM_VALUE(R8
),
289 STRONG_GLENUM_VALUE(RG8
), STRONG_GLENUM_VALUE(R16F
),
290 STRONG_GLENUM_VALUE(R32F
), STRONG_GLENUM_VALUE(RG16F
),
291 STRONG_GLENUM_VALUE(RG32F
), STRONG_GLENUM_VALUE(R8I
),
292 STRONG_GLENUM_VALUE(R8UI
), STRONG_GLENUM_VALUE(R16I
),
293 STRONG_GLENUM_VALUE(R16UI
), STRONG_GLENUM_VALUE(R32I
),
294 STRONG_GLENUM_VALUE(R32UI
), STRONG_GLENUM_VALUE(RG8I
),
295 STRONG_GLENUM_VALUE(RG8UI
), STRONG_GLENUM_VALUE(RG16I
),
296 STRONG_GLENUM_VALUE(RG16UI
), STRONG_GLENUM_VALUE(RG32I
),
297 STRONG_GLENUM_VALUE(RG32UI
),
298 STRONG_GLENUM_VALUE(COMPRESSED_RGB_S3TC_DXT1_EXT
),
299 STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT1_EXT
),
300 STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT3_EXT
),
301 STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT5_EXT
),
302 STRONG_GLENUM_VALUE(COMPRESSED_SRGB_S3TC_DXT1_EXT
),
303 STRONG_GLENUM_VALUE(COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
),
304 STRONG_GLENUM_VALUE(COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
),
305 STRONG_GLENUM_VALUE(COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
),
306 STRONG_GLENUM_VALUE(DEPTH_STENCIL
), STRONG_GLENUM_VALUE(RGBA32F
),
307 STRONG_GLENUM_VALUE(RGB32F
), STRONG_GLENUM_VALUE(ALPHA32F_EXT
),
308 STRONG_GLENUM_VALUE(LUMINANCE32F_EXT
),
309 STRONG_GLENUM_VALUE(LUMINANCE_ALPHA32F_EXT
), STRONG_GLENUM_VALUE(RGBA16F
),
310 STRONG_GLENUM_VALUE(RGB16F
), STRONG_GLENUM_VALUE(ALPHA16F_EXT
),
311 STRONG_GLENUM_VALUE(LUMINANCE16F_EXT
),
312 STRONG_GLENUM_VALUE(LUMINANCE_ALPHA16F_EXT
),
313 STRONG_GLENUM_VALUE(DEPTH24_STENCIL8
),
314 STRONG_GLENUM_VALUE(COMPRESSED_RGB_PVRTC_4BPPV1
),
315 STRONG_GLENUM_VALUE(COMPRESSED_RGB_PVRTC_2BPPV1
),
316 STRONG_GLENUM_VALUE(COMPRESSED_RGBA_PVRTC_4BPPV1
),
317 STRONG_GLENUM_VALUE(COMPRESSED_RGBA_PVRTC_2BPPV1
),
318 STRONG_GLENUM_VALUE(R11F_G11F_B10F
), STRONG_GLENUM_VALUE(RGB9_E5
),
319 STRONG_GLENUM_VALUE(SRGB
), STRONG_GLENUM_VALUE(SRGB8
),
320 STRONG_GLENUM_VALUE(SRGB_ALPHA
), STRONG_GLENUM_VALUE(SRGB8_ALPHA8
),
321 STRONG_GLENUM_VALUE(DEPTH_COMPONENT32F
),
322 STRONG_GLENUM_VALUE(DEPTH32F_STENCIL8
), STRONG_GLENUM_VALUE(RGB565
),
323 STRONG_GLENUM_VALUE(ETC1_RGB8_OES
), STRONG_GLENUM_VALUE(RGBA32UI
),
324 STRONG_GLENUM_VALUE(RGB32UI
), STRONG_GLENUM_VALUE(RGBA16UI
),
325 STRONG_GLENUM_VALUE(RGB16UI
), STRONG_GLENUM_VALUE(RGBA8UI
),
326 STRONG_GLENUM_VALUE(RGB8UI
), STRONG_GLENUM_VALUE(RGBA32I
),
327 STRONG_GLENUM_VALUE(RGB32I
), STRONG_GLENUM_VALUE(RGBA16I
),
328 STRONG_GLENUM_VALUE(RGB16I
), STRONG_GLENUM_VALUE(RGBA8I
),
329 STRONG_GLENUM_VALUE(RGB8I
), STRONG_GLENUM_VALUE(RED_INTEGER
),
330 STRONG_GLENUM_VALUE(RGB_INTEGER
), STRONG_GLENUM_VALUE(RGBA_INTEGER
),
331 STRONG_GLENUM_VALUE(R8_SNORM
), STRONG_GLENUM_VALUE(RG8_SNORM
),
332 STRONG_GLENUM_VALUE(RGB8_SNORM
), STRONG_GLENUM_VALUE(RGBA8_SNORM
),
333 STRONG_GLENUM_VALUE(RGB10_A2UI
),
334 STRONG_GLENUM_END(TexInternalFormat
)
336 STRONG_GLENUM_BEGIN(FBTarget
) STRONG_GLENUM_VALUE(NONE
),
337 STRONG_GLENUM_VALUE(READ_FRAMEBUFFER
),
338 STRONG_GLENUM_VALUE(DRAW_FRAMEBUFFER
), STRONG_GLENUM_VALUE(FRAMEBUFFER
),
339 STRONG_GLENUM_END(FBTarget
)
341 STRONG_GLENUM_BEGIN(RBTarget
) STRONG_GLENUM_VALUE(NONE
),
342 STRONG_GLENUM_VALUE(RENDERBUFFER
),
343 STRONG_GLENUM_END(RBTarget
)
345 STRONG_GLENUM_BEGIN(FBStatus
) STRONG_GLENUM_VALUE(FRAMEBUFFER_COMPLETE
),
346 STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_ATTACHMENT
),
347 STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
),
348 STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_DIMENSIONS
),
349 STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
),
350 STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_READ_BUFFER
),
351 STRONG_GLENUM_VALUE(FRAMEBUFFER_UNSUPPORTED
),
352 STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR
),
353 STRONG_GLENUM_END(FBStatus
)
355 STRONG_GLENUM_BEGIN(RBParam
) STRONG_GLENUM_VALUE(RENDERBUFFER_SAMPLES
),
356 STRONG_GLENUM_VALUE(RENDERBUFFER_WIDTH
),
357 STRONG_GLENUM_VALUE(RENDERBUFFER_HEIGHT
),
358 STRONG_GLENUM_VALUE(RENDERBUFFER_INTERNAL_FORMAT
),
359 STRONG_GLENUM_VALUE(RENDERBUFFER_RED_SIZE
),
360 STRONG_GLENUM_VALUE(RENDERBUFFER_GREEN_SIZE
),
361 STRONG_GLENUM_VALUE(RENDERBUFFER_BLUE_SIZE
),
362 STRONG_GLENUM_VALUE(RENDERBUFFER_ALPHA_SIZE
),
363 STRONG_GLENUM_VALUE(RENDERBUFFER_DEPTH_SIZE
),
364 STRONG_GLENUM_VALUE(RENDERBUFFER_STENCIL_SIZE
),
365 STRONG_GLENUM_END(RBParam
)
367 STRONG_GLENUM_BEGIN(VAOBinding
) STRONG_GLENUM_VALUE(NONE
),
368 STRONG_GLENUM_VALUE(VERTEX_ARRAY_BINDING
),
369 STRONG_GLENUM_END(VAOBinding
)
371 STRONG_GLENUM_BEGIN(BufferBinding
) STRONG_GLENUM_VALUE(NONE
), // 0x0000
372 STRONG_GLENUM_VALUE(ARRAY_BUFFER
), // 0x8892
373 STRONG_GLENUM_VALUE(ELEMENT_ARRAY_BUFFER
), // 0x8893
374 STRONG_GLENUM_VALUE(PIXEL_PACK_BUFFER
), // 0x88EB
375 STRONG_GLENUM_VALUE(PIXEL_UNPACK_BUFFER
), // 0x88EC
376 STRONG_GLENUM_VALUE(UNIFORM_BUFFER
), // 0x8A11
377 STRONG_GLENUM_VALUE(TRANSFORM_FEEDBACK_BUFFER
), // 0x8C8E
378 STRONG_GLENUM_END(BufferBinding
)
380 STRONG_GLENUM_BEGIN(QueryBinding
) STRONG_GLENUM_VALUE(NONE
),
381 STRONG_GLENUM_VALUE(TIME_ELAPSED_EXT
), STRONG_GLENUM_VALUE(TIMESTAMP_EXT
),
382 STRONG_GLENUM_END(QueryBinding
)
384 #endif // WEBGL_STRONG_TYPES_H_