WebGLStrongTypes.h (16137B)
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/. */ 5 6 #ifndef WEBGL_STRONG_TYPES_H_ 7 #define WEBGL_STRONG_TYPES_H_ 8 9 #include <algorithm> 10 #include <array> 11 12 #include "GLDefs.h" 13 #include "mozilla/Assertions.h" 14 #include "mozilla/Attributes.h" 15 16 /* Usage: 17 * =========== 18 * 19 * To create a new type from a set of GLenums do the following: 20 * 21 * STRONG_GLENUM_BEGIN(TypeName) 22 * STRONG_GLENUM_VALUE(ENUM1), 23 * STRONG_GLENUM_VALUE(ENUM2), 24 * ... 25 * STRONG_GLENUM_END() 26 * 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. 29 * 30 * ~~~~~~~~~~~~~~~~ 31 * Important Notes: 32 * ~~~~~~~~~~~~~~~~ 33 * 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: 37 * 38 * if (myNewType == STRONG_GLENUM_VALUE(SOME_ENUM)) 39 * ... 40 * 41 * The operators will assert that STRONG_GLENUM_VALUE(SOME_ENUM) is a value that 42 * myNewType can have. 43 * 44 * ---- 45 * 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. 49 * 50 * Definitely XXX - DO NOT DO - XXX: 51 * 52 * if (myNewType.get() == STRONG_GLENUM_VALUE(SOME_ENUM)) 53 * ... 54 * 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. 57 * 58 * Background: 59 * =========== 60 * 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: 65 * 66 * GL_TEXTURE_2D 67 * GL_TEXTURE_CUBE_MAP 68 * 69 * Yet, this is not the same as texture image targets: 70 * 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 * ... 76 * 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. 81 * 82 * Comparison between STRONG_GLENUM's vs. enum classes 83 * =================================================== 84 * 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). 90 * 91 * When to use GLenum's vs. STRONG_GLENUM's vs. enum classes 92 * ========================================================= 93 * 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. 99 */ 100 101 template <typename Details> 102 class StrongGLenum final { 103 private: 104 static const GLenum NonexistantGLenum = 0xdeaddead; 105 106 GLenum mValue; 107 108 static void AssertOnceThatEnumValuesAreSorted() { 109 #ifdef DEBUG 110 static bool alreadyChecked = false; 111 if (alreadyChecked) { 112 return; 113 } 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"); 117 } 118 alreadyChecked = true; 119 #endif 120 } 121 122 public: 123 StrongGLenum() : mValue(NonexistantGLenum) { 124 AssertOnceThatEnumValuesAreSorted(); 125 } 126 127 MOZ_IMPLICIT StrongGLenum(GLenum value) : mValue(value) { 128 AssertOnceThatEnumValuesAreSorted(); 129 MOZ_ASSERT(IsValueLegal(mValue)); 130 } 131 132 GLenum get() const { 133 MOZ_ASSERT(mValue != NonexistantGLenum); 134 return mValue; 135 } 136 137 bool operator==(const StrongGLenum& other) const { 138 return get() == other.get(); 139 } 140 141 bool operator!=(const StrongGLenum& other) const { 142 return get() != other.get(); 143 } 144 145 bool operator<=(const StrongGLenum& other) const { 146 return get() <= other.get(); 147 } 148 149 bool operator>=(const StrongGLenum& other) const { 150 return get() >= other.get(); 151 } 152 153 explicit operator bool() const { return bool(get()); } 154 155 static bool IsValueLegal(GLenum value) { 156 if (value > UINT16_MAX) { 157 return false; 158 } 159 return std::binary_search(Details::values(), 160 Details::values() + Details::valuesCount(), 161 uint16_t(value)); 162 } 163 }; 164 165 template <typename Details> 166 bool operator==(GLenum a, StrongGLenum<Details> b) { 167 return a == b.get(); 168 } 169 170 template <typename Details> 171 bool operator!=(GLenum a, StrongGLenum<Details> b) { 172 return a != b.get(); 173 } 174 175 template <typename Details> 176 bool operator==(StrongGLenum<Details> a, GLenum b) { 177 return a.get() == b; 178 } 179 180 template <typename Details> 181 bool operator!=(StrongGLenum<Details> a, GLenum b) { 182 return a.get() != b; 183 } 184 185 #define STRONG_GLENUM_BEGIN(NAME) const uint16_t NAME##Values[] = { 186 #define STRONG_GLENUM_VALUE(VALUE) LOCAL_GL_##VALUE 187 188 #define STRONG_GLENUM_END(NAME) \ 189 } \ 190 ; \ 191 struct NAME##Details { \ 192 static size_t valuesCount() { return std::size(NAME##Values); } \ 193 static const uint16_t* values() { return NAME##Values; } \ 194 }; \ 195 typedef StrongGLenum<NAME##Details> NAME; 196 197 //////////////////////////////////////////////////////////////////////////////// 198 // Add types below. 199 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) 211 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) 217 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) 233 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) 240 241 STRONG_GLENUM_BEGIN(TexMagFilter) STRONG_GLENUM_VALUE(NEAREST), 242 STRONG_GLENUM_VALUE(LINEAR), 243 STRONG_GLENUM_END(TexMagFilter) 244 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) 248 249 STRONG_GLENUM_BEGIN(TexCompareMode) STRONG_GLENUM_VALUE(NONE), 250 STRONG_GLENUM_VALUE(COMPARE_REF_TO_TEXTURE), 251 STRONG_GLENUM_END(TexCompareMode) 252 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) 259 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) 277 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) 335 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) 340 341 STRONG_GLENUM_BEGIN(RBTarget) STRONG_GLENUM_VALUE(NONE), 342 STRONG_GLENUM_VALUE(RENDERBUFFER), 343 STRONG_GLENUM_END(RBTarget) 344 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) 354 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) 366 367 STRONG_GLENUM_BEGIN(VAOBinding) STRONG_GLENUM_VALUE(NONE), 368 STRONG_GLENUM_VALUE(VERTEX_ARRAY_BINDING), 369 STRONG_GLENUM_END(VAOBinding) 370 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) 379 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) 383 384 #endif // WEBGL_STRONG_TYPES_H_