Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / canvas / WebGLStrongTypes.h
blob097cd57b29bfed1a0fa049b8da7bcaac258500dc
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_
9 #include <algorithm>
11 #include "GLDefs.h"
12 #include "mozilla/ArrayUtils.h"
13 #include "mozilla/Assertions.h"
14 #include "mozilla/Attributes.h"
16 /* Usage:
17 * ===========
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),
24 * ...
25 * STRONG_GLENUM_END()
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.
30 * ~~~~~~~~~~~~~~~~
31 * Important Notes:
32 * ~~~~~~~~~~~~~~~~
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))
39 * ...
41 * The operators will assert that STRONG_GLENUM_VALUE(SOME_ENUM) is a value that
42 * myNewType can have.
44 * ----
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))
53 * ...
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.
58 * Background:
59 * ===========
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:
66 * GL_TEXTURE_2D
67 * GL_TEXTURE_CUBE_MAP
69 * Yet, this is not the same as texture image targets:
71 * GL_TEXTURE_2D
72 * GL_TEXTURE_CUBE_MAP_POSITIVE_X
73 * GL_TEXTURE_CUBE_MAP_NEGATIVE_X
74 * GL_TEXTURE_CUBE_MAP_POSITIVE_Y
75 * ...
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
89 * opposite).
91 * When to use GLenum's vs. STRONG_GLENUM's vs. enum classes
92 * =========================================================
94 * Rule of thumb:
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 {
103 private:
104 static const GLenum NonexistantGLenum = 0xdeaddead;
106 GLenum mValue;
108 static void AssertOnceThatEnumValuesAreSorted() {
109 #ifdef DEBUG
110 static bool alreadyChecked = false;
111 if (alreadyChecked) {
112 return;
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;
119 #endif
122 public:
123 StrongGLenum() : mValue(NonexistantGLenum) {
124 AssertOnceThatEnumValuesAreSorted();
127 MOZ_IMPLICIT StrongGLenum(GLenum value) : mValue(value) {
128 AssertOnceThatEnumValuesAreSorted();
129 MOZ_ASSERT(IsValueLegal(mValue));
132 GLenum get() const {
133 MOZ_ASSERT(mValue != NonexistantGLenum);
134 return mValue;
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) {
157 return false;
159 return std::binary_search(Details::values(),
160 Details::values() + Details::valuesCount(),
161 uint16_t(value));
165 template <typename Details>
166 bool operator==(GLenum a, StrongGLenum<Details> b) {
167 return a == b.get();
170 template <typename Details>
171 bool operator!=(GLenum a, StrongGLenum<Details> b) {
172 return a != b.get();
175 template <typename Details>
176 bool operator==(StrongGLenum<Details> a, GLenum b) {
177 return a.get() == b;
180 template <typename Details>
181 bool operator!=(StrongGLenum<Details> a, GLenum b) {
182 return a.get() != 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; } \
194 }; \
195 typedef StrongGLenum<NAME##Details> NAME;
197 ////////////////////////////////////////////////////////////////////////////////
198 // Add types below.
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_