summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/js')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/desktop-gl-constants.js2656
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js393
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/glsl-constructor-tests-generator.js936
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/glsl-generator.js1251
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/js-test-post.js29
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/js-test-pre.js744
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/pnglib.js207
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/test-eval.js32
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js109
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js150
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js140
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js200
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js1092
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js280
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js122
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js173
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js183
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js343
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js329
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js320
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js67
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js267
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js263
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js148
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js299
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js249
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js304
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js233
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js67
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js60
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js61
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js276
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js277
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js260
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js204
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js818
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js408
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js580
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js90
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js89
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/webgl-test-harness.js659
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js3122
51 files changed, 19165 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/js/desktop-gl-constants.js b/dom/canvas/test/webgl-conf/checkout/js/desktop-gl-constants.js
new file mode 100644
index 000000000..3ad7d0be2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/desktop-gl-constants.js
@@ -0,0 +1,2656 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// Defines a bunch of DesktopGL constants so we can make sure WebGL
+// implementations disallow them.
+
+// Some of these are also GLES2/GLES3 constants that have been removed from
+// WebGL.
+
+var desktopGL = {
+ 'MIN': 0x8007,
+ 'MAX': 0x8008,
+ 'QUADS': 0x0007,
+ 'QUAD_STRIP': 0x0008,
+ 'POLYGON': 0x0009,
+ '1': 0x0001,
+ '2': 0x0002,
+ '3': 0x0003,
+ '4': 0x0004,
+ 'STATIC_READ': 0x88E5,
+ 'CLIP_PLANE0': 0x3000,
+ 'PERSPECTIVE_CORRECTION_HINT': 0x0C50,
+ 'ACCUM_BUFFER_BIT': 0x0200,
+ 'RGB4': 0x804F,
+ 'RGB5': 0x8050,
+ 'RGB8': 0x8051,
+ 'RGB10': 0x8052,
+ 'RGB12': 0x8053,
+ 'RGB16': 0x8054,
+ 'RGBA2': 0x8055,
+ 'RGBA4': 0x8056,
+ 'RGB5_A1': 0x8057,
+ 'RGBA8': 0x8058,
+ 'RGB10_A2': 0x8059,
+ 'RGBA12': 0x805A,
+ 'RGBA16': 0x805B,
+ 'SMOOTH_POINT_SIZE_RANGE': 0x0B12,
+ 'SMOOTH_POINT_SIZE_GRANULARITY': 0x0B13,
+ 'SMOOTH_LINE_WIDTH_RANGE': 0x0B22,
+ 'SMOOTH_LINE_WIDTH_GRANULARITY': 0x0B23,
+ 'UNSIGNED_BYTE_3_3_2': 0x8032,
+ 'UNSIGNED_SHORT_4_4_4_4': 0x8033,
+ 'UNSIGNED_SHORT_5_5_5_1': 0x8034,
+ 'UNSIGNED_INT_8_8_8_8': 0x8035,
+ 'UNSIGNED_INT_10_10_10_2': 0x8036,
+ 'RESCALE_NORMAL': 0x803A,
+ 'TEXTURE_BINDING_3D': 0x806A,
+ 'PACK_SKIP_IMAGES': 0x806B,
+ 'PACK_IMAGE_HEIGHT': 0x806C,
+ 'UNPACK_SKIP_IMAGES': 0x806D,
+ 'UNPACK_IMAGE_HEIGHT': 0x806E,
+ 'TEXTURE_3D': 0x806F,
+ 'PROXY_TEXTURE_3D': 0x8070,
+ 'TEXTURE_DEPTH': 0x8071,
+ 'TEXTURE_WRAP_R': 0x8072,
+ 'MAX_3D_TEXTURE_SIZE': 0x8073,
+ 'BGR': 0x80E0,
+ 'BGRA': 0x80E1,
+ 'MAX_ELEMENTS_VERTICES': 0x80E8,
+ 'MAX_ELEMENTS_INDICES': 0x80E9,
+ 'CLAMP_TO_EDGE': 0x812F,
+ 'TEXTURE_MIN_LOD': 0x813A,
+ 'TEXTURE_MAX_LOD': 0x813B,
+ 'TEXTURE_BASE_LEVEL': 0x813C,
+ 'TEXTURE_MAX_LEVEL': 0x813D,
+ 'LIGHT_MODEL_COLOR_CONTROL': 0x81F8,
+ 'SINGLE_COLOR': 0x81F9,
+ 'SEPARATE_SPECULAR_COLOR': 0x81FA,
+ 'UNSIGNED_BYTE_2_3_3_REV': 0x8362,
+ 'UNSIGNED_SHORT_5_6_5': 0x8363,
+ 'UNSIGNED_SHORT_5_6_5_REV': 0x8364,
+ 'UNSIGNED_SHORT_4_4_4_4_REV': 0x8365,
+ 'UNSIGNED_SHORT_1_5_5_5_REV': 0x8366,
+ 'UNSIGNED_INT_8_8_8_8_REV': 0x8367,
+ 'UNSIGNED_INT_2_10_10_10_REV': 0x8368,
+ 'ALIASED_POINT_SIZE_RANGE': 0x846D,
+ 'ALIASED_LINE_WIDTH_RANGE': 0x846E,
+ 'MULTISAMPLE': 0x809D,
+ 'SAMPLE_ALPHA_TO_COVERAGE': 0x809E,
+ 'SAMPLE_ALPHA_TO_ONE': 0x809F,
+ 'SAMPLE_COVERAGE': 0x80A0,
+ 'SAMPLE_BUFFERS': 0x80A8,
+ 'SAMPLES': 0x80A9,
+ 'SAMPLE_COVERAGE_VALUE': 0x80AA,
+ 'SAMPLE_COVERAGE_INVERT': 0x80AB,
+ 'CLAMP_TO_BORDER': 0x812D,
+ 'TEXTURE0': 0x84C0,
+ 'TEXTURE1': 0x84C1,
+ 'TEXTURE2': 0x84C2,
+ 'TEXTURE3': 0x84C3,
+ 'TEXTURE4': 0x84C4,
+ 'TEXTURE5': 0x84C5,
+ 'TEXTURE6': 0x84C6,
+ 'TEXTURE7': 0x84C7,
+ 'TEXTURE8': 0x84C8,
+ 'TEXTURE9': 0x84C9,
+ 'TEXTURE10': 0x84CA,
+ 'TEXTURE11': 0x84CB,
+ 'TEXTURE12': 0x84CC,
+ 'TEXTURE13': 0x84CD,
+ 'TEXTURE14': 0x84CE,
+ 'TEXTURE15': 0x84CF,
+ 'TEXTURE16': 0x84D0,
+ 'TEXTURE17': 0x84D1,
+ 'TEXTURE18': 0x84D2,
+ 'TEXTURE19': 0x84D3,
+ 'TEXTURE20': 0x84D4,
+ 'TEXTURE21': 0x84D5,
+ 'TEXTURE22': 0x84D6,
+ 'TEXTURE23': 0x84D7,
+ 'TEXTURE24': 0x84D8,
+ 'TEXTURE25': 0x84D9,
+ 'TEXTURE26': 0x84DA,
+ 'TEXTURE27': 0x84DB,
+ 'TEXTURE28': 0x84DC,
+ 'TEXTURE29': 0x84DD,
+ 'TEXTURE30': 0x84DE,
+ 'TEXTURE31': 0x84DF,
+ 'ACTIVE_TEXTURE': 0x84E0,
+ 'CLIENT_ACTIVE_TEXTURE': 0x84E1,
+ 'MAX_TEXTURE_UNITS': 0x84E2,
+ 'TRANSPOSE_MODELVIEW_MATRIX': 0x84E3,
+ 'TRANSPOSE_PROJECTION_MATRIX': 0x84E4,
+ 'TRANSPOSE_TEXTURE_MATRIX': 0x84E5,
+ 'TRANSPOSE_COLOR_MATRIX': 0x84E6,
+ 'SUBTRACT': 0x84E7,
+ 'COMPRESSED_ALPHA': 0x84E9,
+ 'COMPRESSED_LUMINANCE': 0x84EA,
+ 'COMPRESSED_LUMINANCE_ALPHA': 0x84EB,
+ 'COMPRESSED_INTENSITY': 0x84EC,
+ 'COMPRESSED_RGB': 0x84ED,
+ 'COMPRESSED_RGBA': 0x84EE,
+ 'TEXTURE_COMPRESSION_HINT': 0x84EF,
+ 'NORMAL_MAP': 0x8511,
+ 'REFLECTION_MAP': 0x8512,
+ 'TEXTURE_CUBE_MAP': 0x8513,
+ 'TEXTURE_BINDING_CUBE_MAP': 0x8514,
+ 'TEXTURE_CUBE_MAP_POSITIVE_X': 0x8515,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_X': 0x8516,
+ 'TEXTURE_CUBE_MAP_POSITIVE_Y': 0x8517,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_Y': 0x8518,
+ 'TEXTURE_CUBE_MAP_POSITIVE_Z': 0x8519,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_Z': 0x851A,
+ 'PROXY_TEXTURE_CUBE_MAP': 0x851B,
+ 'MAX_CUBE_MAP_TEXTURE_SIZE': 0x851C,
+ 'COMBINE': 0x8570,
+ 'COMBINE_RGB': 0x8571,
+ 'COMBINE_ALPHA': 0x8572,
+ 'RGB_SCALE': 0x8573,
+ 'ADD_SIGNED': 0x8574,
+ 'INTERPOLATE': 0x8575,
+ 'CONSTANT': 0x8576,
+ 'PRIMARY_COLOR': 0x8577,
+ 'PREVIOUS': 0x8578,
+ 'SOURCE0_RGB': 0x8580,
+ 'SOURCE1_RGB': 0x8581,
+ 'SOURCE2_RGB': 0x8582,
+ 'SOURCE0_ALPHA': 0x8588,
+ 'SOURCE1_ALPHA': 0x8589,
+ 'SOURCE2_ALPHA': 0x858A,
+ 'OPERAND0_RGB': 0x8590,
+ 'OPERAND1_RGB': 0x8591,
+ 'OPERAND2_RGB': 0x8592,
+ 'OPERAND0_ALPHA': 0x8598,
+ 'OPERAND1_ALPHA': 0x8599,
+ 'OPERAND2_ALPHA': 0x859A,
+ 'TEXTURE_COMPRESSED_IMAGE_SIZE': 0x86A0,
+ 'TEXTURE_COMPRESSED': 0x86A1,
+ 'NUM_COMPRESSED_TEXTURE_FORMATS': 0x86A2,
+ 'COMPRESSED_TEXTURE_FORMATS': 0x86A3,
+ 'DOT3_RGB': 0x86AE,
+ 'DOT3_RGBA': 0x86AF,
+ 'MULTISAMPLE_BIT': 0x20000000,
+ 'BLEND_DST_RGB': 0x80C8,
+ 'BLEND_SRC_RGB': 0x80C9,
+ 'BLEND_DST_ALPHA': 0x80CA,
+ 'BLEND_SRC_ALPHA': 0x80CB,
+ 'POINT_SIZE_MIN': 0x8126,
+ 'POINT_SIZE_MAX': 0x8127,
+ 'POINT_FADE_THRESHOLD_SIZE': 0x8128,
+ 'POINT_DISTANCE_ATTENUATION': 0x8129,
+ 'GENERATE_MIPMAP': 0x8191,
+ 'GENERATE_MIPMAP_HINT': 0x8192,
+ 'DEPTH_COMPONENT16': 0x81A5,
+ 'DEPTH_COMPONENT24': 0x81A6,
+ 'DEPTH_COMPONENT32': 0x81A7,
+ 'MIRRORED_REPEAT': 0x8370,
+ 'FOG_COORDINATE_SOURCE': 0x8450,
+ 'FOG_COORDINATE': 0x8451,
+ 'FRAGMENT_DEPTH': 0x8452,
+ 'CURRENT_FOG_COORDINATE': 0x8453,
+ 'FOG_COORDINATE_ARRAY_TYPE': 0x8454,
+ 'FOG_COORDINATE_ARRAY_STRIDE': 0x8455,
+ 'FOG_COORDINATE_ARRAY_POINTER': 0x8456,
+ 'FOG_COORDINATE_ARRAY': 0x8457,
+ 'COLOR_SUM': 0x8458,
+ 'CURRENT_SECONDARY_COLOR': 0x8459,
+ 'SECONDARY_COLOR_ARRAY_SIZE': 0x845A,
+ 'SECONDARY_COLOR_ARRAY_TYPE': 0x845B,
+ 'SECONDARY_COLOR_ARRAY_STRIDE': 0x845C,
+ 'SECONDARY_COLOR_ARRAY_POINTER': 0x845D,
+ 'SECONDARY_COLOR_ARRAY': 0x845E,
+ 'MAX_TEXTURE_LOD_BIAS': 0x84FD,
+ 'TEXTURE_FILTER_CONTROL': 0x8500,
+ 'TEXTURE_LOD_BIAS': 0x8501,
+ 'INCR_WRAP': 0x8507,
+ 'DECR_WRAP': 0x8508,
+ 'TEXTURE_DEPTH_SIZE': 0x884A,
+ 'DEPTH_TEXTURE_MODE': 0x884B,
+ 'TEXTURE_COMPARE_MODE': 0x884C,
+ 'TEXTURE_COMPARE_FUNC': 0x884D,
+ 'COMPARE_R_TO_TEXTURE': 0x884E,
+ 'BUFFER_SIZE': 0x8764,
+ 'BUFFER_USAGE': 0x8765,
+ 'QUERY_COUNTER_BITS': 0x8864,
+ 'CURRENT_QUERY': 0x8865,
+ 'QUERY_RESULT': 0x8866,
+ 'QUERY_RESULT_AVAILABLE': 0x8867,
+ 'ARRAY_BUFFER': 0x8892,
+ 'ELEMENT_ARRAY_BUFFER': 0x8893,
+ 'ARRAY_BUFFER_BINDING': 0x8894,
+ 'ELEMENT_ARRAY_BUFFER_BINDING': 0x8895,
+ 'VERTEX_ARRAY_BUFFER_BINDING': 0x8896,
+ 'NORMAL_ARRAY_BUFFER_BINDING': 0x8897,
+ 'COLOR_ARRAY_BUFFER_BINDING': 0x8898,
+ 'INDEX_ARRAY_BUFFER_BINDING': 0x8899,
+ 'TEXTURE_COORD_ARRAY_BUFFER_BINDING': 0x889A,
+ 'EDGE_FLAG_ARRAY_BUFFER_BINDING': 0x889B,
+ 'SECONDARY_COLOR_ARRAY_BUFFER_BINDING': 0x889C,
+ 'FOG_COORDINATE_ARRAY_BUFFER_BINDING': 0x889D,
+ 'WEIGHT_ARRAY_BUFFER_BINDING': 0x889E,
+ 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING': 0x889F,
+ 'READ_ONLY': 0x88B8,
+ 'WRITE_ONLY': 0x88B9,
+ 'READ_WRITE': 0x88BA,
+ 'BUFFER_ACCESS': 0x88BB,
+ 'BUFFER_MAPPED': 0x88BC,
+ 'BUFFER_MAP_POINTER': 0x88BD,
+ 'STREAM_DRAW': 0x88E0,
+ 'STREAM_READ': 0x88E1,
+ 'STREAM_COPY': 0x88E2,
+ 'STATIC_DRAW': 0x88E4,
+ 'STATIC_READ': 0x88E5,
+ 'STATIC_COPY': 0x88E6,
+ 'DYNAMIC_DRAW': 0x88E8,
+ 'DYNAMIC_READ': 0x88E9,
+ 'DYNAMIC_COPY': 0x88EA,
+ 'SAMPLES_PASSED': 0x8914,
+ 'VERTEX_ATTRIB_ARRAY_ENABLED': 0x8622,
+ 'VERTEX_ATTRIB_ARRAY_SIZE': 0x8623,
+ 'VERTEX_ATTRIB_ARRAY_STRIDE': 0x8624,
+ 'VERTEX_ATTRIB_ARRAY_TYPE': 0x8625,
+ 'CURRENT_VERTEX_ATTRIB': 0x8626,
+ 'VERTEX_PROGRAM_POINT_SIZE': 0x8642,
+ 'VERTEX_PROGRAM_TWO_SIDE': 0x8643,
+ 'VERTEX_ATTRIB_ARRAY_POINTER': 0x8645,
+ 'STENCIL_BACK_FUNC': 0x8800,
+ 'STENCIL_BACK_FAIL': 0x8801,
+ 'STENCIL_BACK_PASS_DEPTH_FAIL': 0x8802,
+ 'STENCIL_BACK_PASS_DEPTH_PASS': 0x8803,
+ 'MAX_DRAW_BUFFERS': 0x8824,
+ 'DRAW_BUFFER0': 0x8825,
+ 'DRAW_BUFFER1': 0x8826,
+ 'DRAW_BUFFER2': 0x8827,
+ 'DRAW_BUFFER3': 0x8828,
+ 'DRAW_BUFFER4': 0x8829,
+ 'DRAW_BUFFER5': 0x882A,
+ 'DRAW_BUFFER6': 0x882B,
+ 'DRAW_BUFFER7': 0x882C,
+ 'DRAW_BUFFER8': 0x882D,
+ 'DRAW_BUFFER9': 0x882E,
+ 'DRAW_BUFFER10': 0x882F,
+ 'DRAW_BUFFER11': 0x8830,
+ 'DRAW_BUFFER12': 0x8831,
+ 'DRAW_BUFFER13': 0x8832,
+ 'DRAW_BUFFER14': 0x8833,
+ 'DRAW_BUFFER15': 0x8834,
+ 'BLEND_EQUATION_ALPHA': 0x883D,
+ 'POINT_SPRITE': 0x8861,
+ 'COORD_REPLACE': 0x8862,
+ 'MAX_VERTEX_ATTRIBS': 0x8869,
+ 'VERTEX_ATTRIB_ARRAY_NORMALIZED': 0x886A,
+ 'MAX_TEXTURE_COORDS': 0x8871,
+ 'MAX_TEXTURE_IMAGE_UNITS': 0x8872,
+ 'FRAGMENT_SHADER': 0x8B30,
+ 'VERTEX_SHADER': 0x8B31,
+ 'MAX_FRAGMENT_UNIFORM_COMPONENTS': 0x8B49,
+ 'MAX_VERTEX_UNIFORM_COMPONENTS': 0x8B4A,
+ 'MAX_VARYING_FLOATS': 0x8B4B,
+ 'MAX_VERTEX_TEXTURE_IMAGE_UNITS': 0x8B4C,
+ 'MAX_COMBINED_TEXTURE_IMAGE_UNITS': 0x8B4D,
+ 'SHADER_TYPE': 0x8B4F,
+ 'FLOAT_VEC2': 0x8B50,
+ 'FLOAT_VEC3': 0x8B51,
+ 'FLOAT_VEC4': 0x8B52,
+ 'INT_VEC2': 0x8B53,
+ 'INT_VEC3': 0x8B54,
+ 'INT_VEC4': 0x8B55,
+ 'BOOL': 0x8B56,
+ 'BOOL_VEC2': 0x8B57,
+ 'BOOL_VEC3': 0x8B58,
+ 'BOOL_VEC4': 0x8B59,
+ 'FLOAT_MAT2': 0x8B5A,
+ 'FLOAT_MAT3': 0x8B5B,
+ 'FLOAT_MAT4': 0x8B5C,
+ 'SAMPLER_1D': 0x8B5D,
+ 'SAMPLER_2D': 0x8B5E,
+ 'SAMPLER_3D': 0x8B5F,
+ 'SAMPLER_CUBE': 0x8B60,
+ 'SAMPLER_1D_SHADOW': 0x8B61,
+ 'SAMPLER_2D_SHADOW': 0x8B62,
+ 'DELETE_STATUS': 0x8B80,
+ 'COMPILE_STATUS': 0x8B81,
+ 'LINK_STATUS': 0x8B82,
+ 'VALIDATE_STATUS': 0x8B83,
+ 'INFO_LOG_LENGTH': 0x8B84,
+ 'ATTACHED_SHADERS': 0x8B85,
+ 'ACTIVE_UNIFORMS': 0x8B86,
+ 'ACTIVE_UNIFORM_MAX_LENGTH': 0x8B87,
+ 'SHADER_SOURCE_LENGTH': 0x8B88,
+ 'ACTIVE_ATTRIBUTES': 0x8B89,
+ 'ACTIVE_ATTRIBUTE_MAX_LENGTH': 0x8B8A,
+ 'FRAGMENT_SHADER_DERIVATIVE_HINT': 0x8B8B,
+ 'SHADING_LANGUAGE_VERSION': 0x8B8C,
+ 'CURRENT_PROGRAM': 0x8B8D,
+ 'POINT_SPRITE_COORD_ORIGIN': 0x8CA0,
+ 'LOWER_LEFT': 0x8CA1,
+ 'UPPER_LEFT': 0x8CA2,
+ 'STENCIL_BACK_REF': 0x8CA3,
+ 'STENCIL_BACK_VALUE_MASK': 0x8CA4,
+ 'STENCIL_BACK_WRITEMASK': 0x8CA5,
+ 'CURRENT_RASTER_SECONDARY_COLOR': 0x845F,
+ 'PIXEL_PACK_BUFFER': 0x88EB,
+ 'PIXEL_UNPACK_BUFFER': 0x88EC,
+ 'PIXEL_PACK_BUFFER_BINDING': 0x88ED,
+ 'PIXEL_UNPACK_BUFFER_BINDING': 0x88EF,
+ 'FLOAT_MAT2x3': 0x8B65,
+ 'FLOAT_MAT2x4': 0x8B66,
+ 'FLOAT_MAT3x2': 0x8B67,
+ 'FLOAT_MAT3x4': 0x8B68,
+ 'FLOAT_MAT4x2': 0x8B69,
+ 'FLOAT_MAT4x3': 0x8B6A,
+ 'SRGB': 0x8C40,
+ 'SRGB8': 0x8C41,
+ 'SRGB_ALPHA': 0x8C42,
+ 'SRGB8_ALPHA8': 0x8C43,
+ 'SLUMINANCE_ALPHA': 0x8C44,
+ 'SLUMINANCE8_ALPHA8': 0x8C45,
+ 'SLUMINANCE': 0x8C46,
+ 'SLUMINANCE8': 0x8C47,
+ 'COMPRESSED_SRGB': 0x8C48,
+ 'COMPRESSED_SRGB_ALPHA': 0x8C49,
+ 'COMPRESSED_SLUMINANCE': 0x8C4A,
+ 'COMPRESSED_SLUMINANCE_ALPHA': 0x8C4B,
+ 'CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT': 0x0001,
+ 'MAJOR_VERSION': 0x821B,
+ 'MINOR_VERSION': 0x821C,
+ 'NUM_EXTENSIONS': 0x821D,
+ 'CONTEXT_FLAGS': 0x821E,
+ 'DEPTH_BUFFER': 0x8223,
+ 'STENCIL_BUFFER': 0x8224,
+ 'COMPRESSED_RED': 0x8225,
+ 'COMPRESSED_RG': 0x8226,
+ 'RGBA32F': 0x8814,
+ 'RGB32F': 0x8815,
+ 'RGBA16F': 0x881A,
+ 'RGB16F': 0x881B,
+ 'VERTEX_ATTRIB_ARRAY_INTEGER': 0x88FD,
+ 'MAX_ARRAY_TEXTURE_LAYERS': 0x88FF,
+ 'MIN_PROGRAM_TEXEL_OFFSET': 0x8904,
+ 'MAX_PROGRAM_TEXEL_OFFSET': 0x8905,
+ 'CLAMP_VERTEX_COLOR': 0x891A,
+ 'CLAMP_FRAGMENT_COLOR': 0x891B,
+ 'CLAMP_READ_COLOR': 0x891C,
+ 'FIXED_ONLY': 0x891D,
+ 'TEXTURE_RED_TYPE': 0x8C10,
+ 'TEXTURE_GREEN_TYPE': 0x8C11,
+ 'TEXTURE_BLUE_TYPE': 0x8C12,
+ 'TEXTURE_ALPHA_TYPE': 0x8C13,
+ 'TEXTURE_LUMINANCE_TYPE': 0x8C14,
+ 'TEXTURE_INTENSITY_TYPE': 0x8C15,
+ 'TEXTURE_DEPTH_TYPE': 0x8C16,
+ 'UNSIGNED_NORMALIZED': 0x8C17,
+ 'TEXTURE_1D_ARRAY': 0x8C18,
+ 'PROXY_TEXTURE_1D_ARRAY': 0x8C19,
+ 'TEXTURE_2D_ARRAY': 0x8C1A,
+ 'PROXY_TEXTURE_2D_ARRAY': 0x8C1B,
+ 'TEXTURE_BINDING_1D_ARRAY': 0x8C1C,
+ 'TEXTURE_BINDING_2D_ARRAY': 0x8C1D,
+ 'R11F_G11F_B10F': 0x8C3A,
+ 'UNSIGNED_INT_10F_11F_11F_REV': 0x8C3B,
+ 'RGB9_E5': 0x8C3D,
+ 'UNSIGNED_INT_5_9_9_9_REV': 0x8C3E,
+ 'TEXTURE_SHARED_SIZE': 0x8C3F,
+ 'TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH': 0x8C76,
+ 'TRANSFORM_FEEDBACK_BUFFER_MODE': 0x8C7F,
+ 'MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS': 0x8C80,
+ 'TRANSFORM_FEEDBACK_VARYINGS': 0x8C83,
+ 'TRANSFORM_FEEDBACK_BUFFER_START': 0x8C84,
+ 'TRANSFORM_FEEDBACK_BUFFER_SIZE': 0x8C85,
+ 'PRIMITIVES_GENERATED': 0x8C87,
+ 'TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN': 0x8C88,
+ 'RASTERIZER_DISCARD': 0x8C89,
+ 'MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS': 0x8C8A,
+ 'MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS': 0x8C8B,
+ 'INTERLEAVED_ATTRIBS': 0x8C8C,
+ 'SEPARATE_ATTRIBS': 0x8C8D,
+ 'TRANSFORM_FEEDBACK_BUFFER': 0x8C8E,
+ 'TRANSFORM_FEEDBACK_BUFFER_BINDING': 0x8C8F,
+ 'RGBA32UI': 0x8D70,
+ 'RGB32UI': 0x8D71,
+ 'RGBA16UI': 0x8D76,
+ 'RGB16UI': 0x8D77,
+ 'RGBA8UI': 0x8D7C,
+ 'RGB8UI': 0x8D7D,
+ 'RGBA32I': 0x8D82,
+ 'RGB32I': 0x8D83,
+ 'RGBA16I': 0x8D88,
+ 'RGB16I': 0x8D89,
+ 'RGBA8I': 0x8D8E,
+ 'RGB8I': 0x8D8F,
+ 'RED_INTEGER': 0x8D94,
+ 'GREEN_INTEGER': 0x8D95,
+ 'BLUE_INTEGER': 0x8D96,
+ 'ALPHA_INTEGER': 0x8D97,
+ 'RGB_INTEGER': 0x8D98,
+ 'RGBA_INTEGER': 0x8D99,
+ 'BGR_INTEGER': 0x8D9A,
+ 'BGRA_INTEGER': 0x8D9B,
+ 'SAMPLER_1D_ARRAY': 0x8DC0,
+ 'SAMPLER_2D_ARRAY': 0x8DC1,
+ 'SAMPLER_1D_ARRAY_SHADOW': 0x8DC3,
+ 'SAMPLER_2D_ARRAY_SHADOW': 0x8DC4,
+ 'SAMPLER_CUBE_SHADOW': 0x8DC5,
+ 'UNSIGNED_INT_VEC2': 0x8DC6,
+ 'UNSIGNED_INT_VEC3': 0x8DC7,
+ 'UNSIGNED_INT_VEC4': 0x8DC8,
+ 'INT_SAMPLER_1D': 0x8DC9,
+ 'INT_SAMPLER_2D': 0x8DCA,
+ 'INT_SAMPLER_3D': 0x8DCB,
+ 'INT_SAMPLER_CUBE': 0x8DCC,
+ 'INT_SAMPLER_1D_ARRAY': 0x8DCE,
+ 'INT_SAMPLER_2D_ARRAY': 0x8DCF,
+ 'UNSIGNED_INT_SAMPLER_1D': 0x8DD1,
+ 'UNSIGNED_INT_SAMPLER_2D': 0x8DD2,
+ 'UNSIGNED_INT_SAMPLER_3D': 0x8DD3,
+ 'UNSIGNED_INT_SAMPLER_CUBE': 0x8DD4,
+ 'UNSIGNED_INT_SAMPLER_1D_ARRAY': 0x8DD6,
+ 'UNSIGNED_INT_SAMPLER_2D_ARRAY': 0x8DD7,
+ 'QUERY_WAIT': 0x8E13,
+ 'QUERY_NO_WAIT': 0x8E14,
+ 'QUERY_BY_REGION_WAIT': 0x8E15,
+ 'QUERY_BY_REGION_NO_WAIT': 0x8E16,
+ 'MULTISAMPLE_3DFX': 0x86B2,
+ 'SAMPLE_BUFFERS_3DFX': 0x86B3,
+ 'SAMPLES_3DFX': 0x86B4,
+ 'MULTISAMPLE_BIT_3DFX': 0x20000000,
+ 'COMPRESSED_RGB_FXT1_3DFX': 0x86B0,
+ 'COMPRESSED_RGBA_FXT1_3DFX': 0x86B1,
+ 'UNPACK_CLIENT_STORAGE_APPLE': 0x85B2,
+ 'ELEMENT_ARRAY_APPLE': 0x8768,
+ 'ELEMENT_ARRAY_TYPE_APPLE': 0x8769,
+ 'ELEMENT_ARRAY_POINTER_APPLE': 0x876A,
+ 'HALF_APPLE': 0x140B,
+ 'RGBA_FLOAT32_APPLE': 0x8814,
+ 'RGB_FLOAT32_APPLE': 0x8815,
+ 'ALPHA_FLOAT32_APPLE': 0x8816,
+ 'INTENSITY_FLOAT32_APPLE': 0x8817,
+ 'LUMINANCE_FLOAT32_APPLE': 0x8818,
+ 'LUMINANCE_ALPHA_FLOAT32_APPLE': 0x8819,
+ 'RGBA_FLOAT16_APPLE': 0x881A,
+ 'RGB_FLOAT16_APPLE': 0x881B,
+ 'ALPHA_FLOAT16_APPLE': 0x881C,
+ 'INTENSITY_FLOAT16_APPLE': 0x881D,
+ 'LUMINANCE_FLOAT16_APPLE': 0x881E,
+ 'LUMINANCE_ALPHA_FLOAT16_APPLE': 0x881F,
+ 'COLOR_FLOAT_APPLE': 0x8A0F,
+ 'BUFFER_SERIALIZED_MODIFY_APPLE': 0x8A12,
+ 'BUFFER_FLUSHING_UNMAP_APPLE': 0x8A13,
+ 'MIN_PBUFFER_VIEWPORT_DIMS_APPLE': 0x8A10,
+ 'LIGHT_MODEL_SPECULAR_VECTOR_APPLE': 0x85B0,
+ 'TEXTURE_RANGE_LENGTH_APPLE': 0x85B7,
+ 'TEXTURE_RANGE_POINTER_APPLE': 0x85B8,
+ 'TEXTURE_STORAGE_HINT_APPLE': 0x85BC,
+ 'STORAGE_PRIVATE_APPLE': 0x85BD,
+ 'STORAGE_CACHED_APPLE': 0x85BE,
+ 'STORAGE_SHARED_APPLE': 0x85BF,
+ 'TRANSFORM_HINT_APPLE': 0x85B1,
+ 'VERTEX_ARRAY_BINDING_APPLE': 0x85B5,
+ 'VERTEX_ARRAY_RANGE_APPLE': 0x851D,
+ 'VERTEX_ARRAY_RANGE_LENGTH_APPLE': 0x851E,
+ 'VERTEX_ARRAY_STORAGE_HINT_APPLE': 0x851F,
+ 'MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE': 0x8520,
+ 'VERTEX_ARRAY_RANGE_POINTER_APPLE': 0x8521,
+ 'STORAGE_CACHED_APPLE': 0x85BE,
+ 'STORAGE_SHARED_APPLE': 0x85BF,
+ 'YCBCR_422_APPLE': 0x85B9,
+ 'UNSIGNED_SHORT_8_8_APPLE': 0x85BA,
+ 'UNSIGNED_SHORT_8_8_REV_APPLE': 0x85BB,
+ 'RGBA_FLOAT_MODE_ARB': 0x8820,
+ 'CLAMP_VERTEX_COLOR_ARB': 0x891A,
+ 'CLAMP_FRAGMENT_COLOR_ARB': 0x891B,
+ 'CLAMP_READ_COLOR_ARB': 0x891C,
+ 'FIXED_ONLY_ARB': 0x891D,
+ 'DEPTH_COMPONENT32F': 0x8CAC,
+ 'DEPTH32F_STENCIL8': 0x8CAD,
+ 'FLOAT_32_UNSIGNED_INT_24_8_REV': 0x8DAD,
+ 'DEPTH_COMPONENT16_ARB': 0x81A5,
+ 'DEPTH_COMPONENT24_ARB': 0x81A6,
+ 'DEPTH_COMPONENT32_ARB': 0x81A7,
+ 'TEXTURE_DEPTH_SIZE_ARB': 0x884A,
+ 'DEPTH_TEXTURE_MODE_ARB': 0x884B,
+ 'MAX_DRAW_BUFFERS_ARB': 0x8824,
+ 'DRAW_BUFFER0_ARB': 0x8825,
+ 'DRAW_BUFFER1_ARB': 0x8826,
+ 'DRAW_BUFFER2_ARB': 0x8827,
+ 'DRAW_BUFFER3_ARB': 0x8828,
+ 'DRAW_BUFFER4_ARB': 0x8829,
+ 'DRAW_BUFFER5_ARB': 0x882A,
+ 'DRAW_BUFFER6_ARB': 0x882B,
+ 'DRAW_BUFFER7_ARB': 0x882C,
+ 'DRAW_BUFFER8_ARB': 0x882D,
+ 'DRAW_BUFFER9_ARB': 0x882E,
+ 'DRAW_BUFFER10_ARB': 0x882F,
+ 'DRAW_BUFFER11_ARB': 0x8830,
+ 'DRAW_BUFFER12_ARB': 0x8831,
+ 'DRAW_BUFFER13_ARB': 0x8832,
+ 'DRAW_BUFFER14_ARB': 0x8833,
+ 'DRAW_BUFFER15_ARB': 0x8834,
+ 'FRAGMENT_PROGRAM_ARB': 0x8804,
+ 'PROGRAM_ALU_INSTRUCTIONS_ARB': 0x8805,
+ 'PROGRAM_TEX_INSTRUCTIONS_ARB': 0x8806,
+ 'PROGRAM_TEX_INDIRECTIONS_ARB': 0x8807,
+ 'PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB': 0x8808,
+ 'PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB': 0x8809,
+ 'PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB': 0x880A,
+ 'MAX_PROGRAM_ALU_INSTRUCTIONS_ARB': 0x880B,
+ 'MAX_PROGRAM_TEX_INSTRUCTIONS_ARB': 0x880C,
+ 'MAX_PROGRAM_TEX_INDIRECTIONS_ARB': 0x880D,
+ 'MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB': 0x880E,
+ 'MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB': 0x880F,
+ 'MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB': 0x8810,
+ 'MAX_TEXTURE_COORDS_ARB': 0x8871,
+ 'MAX_TEXTURE_IMAGE_UNITS_ARB': 0x8872,
+ 'FRAGMENT_SHADER_ARB': 0x8B30,
+ 'MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB': 0x8B49,
+ 'FRAGMENT_SHADER_DERIVATIVE_HINT_ARB': 0x8B8B,
+ 'INVALID_FRAMEBUFFER_OPERATION': 0x0506,
+ 'FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING': 0x8210,
+ 'FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE': 0x8211,
+ 'FRAMEBUFFER_ATTACHMENT_RED_SIZE': 0x8212,
+ 'FRAMEBUFFER_ATTACHMENT_GREEN_SIZE': 0x8213,
+ 'FRAMEBUFFER_ATTACHMENT_BLUE_SIZE': 0x8214,
+ 'FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE': 0x8215,
+ 'FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE': 0x8216,
+ 'FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE': 0x8217,
+ 'FRAMEBUFFER_DEFAULT': 0x8218,
+ 'FRAMEBUFFER_UNDEFINED': 0x8219,
+ 'DEPTH_STENCIL_ATTACHMENT': 0x821A,
+ 'INDEX': 0x8222,
+ 'MAX_RENDERBUFFER_SIZE': 0x84E8,
+ 'DEPTH_STENCIL': 0x84F9,
+ 'UNSIGNED_INT_24_8': 0x84FA,
+ 'DEPTH24_STENCIL8': 0x88F0,
+ 'TEXTURE_STENCIL_SIZE': 0x88F1,
+ 'UNSIGNED_NORMALIZED': 0x8C17,
+ 'SRGB': 0x8C40,
+ 'DRAW_FRAMEBUFFER_BINDING': 0x8CA6,
+ 'FRAMEBUFFER_BINDING': 0x8CA6,
+ 'RENDERBUFFER_BINDING': 0x8CA7,
+ 'READ_FRAMEBUFFER': 0x8CA8,
+ 'DRAW_FRAMEBUFFER': 0x8CA9,
+ 'READ_FRAMEBUFFER_BINDING': 0x8CAA,
+ 'RENDERBUFFER_SAMPLES': 0x8CAB,
+ 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE': 0x8CD0,
+ 'FRAMEBUFFER_ATTACHMENT_OBJECT_NAME': 0x8CD1,
+ 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL': 0x8CD2,
+ 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE': 0x8CD3,
+ 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER': 0x8CD4,
+ 'FRAMEBUFFER_COMPLETE': 0x8CD5,
+ 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT': 0x8CD6,
+ 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT': 0x8CD7,
+ 'FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER': 0x8CDB,
+ 'FRAMEBUFFER_INCOMPLETE_READ_BUFFER': 0x8CDC,
+ 'FRAMEBUFFER_UNSUPPORTED': 0x8CDD,
+ 'MAX_COLOR_ATTACHMENTS': 0x8CDF,
+ 'COLOR_ATTACHMENT0': 0x8CE0,
+ 'COLOR_ATTACHMENT1': 0x8CE1,
+ 'COLOR_ATTACHMENT2': 0x8CE2,
+ 'COLOR_ATTACHMENT3': 0x8CE3,
+ 'COLOR_ATTACHMENT4': 0x8CE4,
+ 'COLOR_ATTACHMENT5': 0x8CE5,
+ 'COLOR_ATTACHMENT6': 0x8CE6,
+ 'COLOR_ATTACHMENT7': 0x8CE7,
+ 'COLOR_ATTACHMENT8': 0x8CE8,
+ 'COLOR_ATTACHMENT9': 0x8CE9,
+ 'COLOR_ATTACHMENT10': 0x8CEA,
+ 'COLOR_ATTACHMENT11': 0x8CEB,
+ 'COLOR_ATTACHMENT12': 0x8CEC,
+ 'COLOR_ATTACHMENT13': 0x8CED,
+ 'COLOR_ATTACHMENT14': 0x8CEE,
+ 'COLOR_ATTACHMENT15': 0x8CEF,
+ 'DEPTH_ATTACHMENT': 0x8D00,
+ 'STENCIL_ATTACHMENT': 0x8D20,
+ 'FRAMEBUFFER': 0x8D40,
+ 'RENDERBUFFER': 0x8D41,
+ 'RENDERBUFFER_WIDTH': 0x8D42,
+ 'RENDERBUFFER_HEIGHT': 0x8D43,
+ 'RENDERBUFFER_INTERNAL_FORMAT': 0x8D44,
+ 'STENCIL_INDEX1': 0x8D46,
+ 'STENCIL_INDEX4': 0x8D47,
+ 'STENCIL_INDEX8': 0x8D48,
+ 'STENCIL_INDEX16': 0x8D49,
+ 'RENDERBUFFER_RED_SIZE': 0x8D50,
+ 'RENDERBUFFER_GREEN_SIZE': 0x8D51,
+ 'RENDERBUFFER_BLUE_SIZE': 0x8D52,
+ 'RENDERBUFFER_ALPHA_SIZE': 0x8D53,
+ 'RENDERBUFFER_DEPTH_SIZE': 0x8D54,
+ 'RENDERBUFFER_STENCIL_SIZE': 0x8D55,
+ 'FRAMEBUFFER_INCOMPLETE_MULTISAMPLE': 0x8D56,
+ 'MAX_SAMPLES': 0x8D57,
+ 'FRAMEBUFFER_SRGB': 0x8DB9,
+ 'LINES_ADJACENCY_ARB': 0xA,
+ 'LINE_STRIP_ADJACENCY_ARB': 0xB,
+ 'TRIANGLES_ADJACENCY_ARB': 0xC,
+ 'TRIANGLE_STRIP_ADJACENCY_ARB': 0xD,
+ 'PROGRAM_POINT_SIZE_ARB': 0x8642,
+ 'MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB': 0x8C29,
+ 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER': 0x8CD4,
+ 'FRAMEBUFFER_ATTACHMENT_LAYERED_ARB': 0x8DA7,
+ 'FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB': 0x8DA8,
+ 'FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB': 0x8DA9,
+ 'GEOMETRY_SHADER_ARB': 0x8DD9,
+ 'GEOMETRY_VERTICES_OUT_ARB': 0x8DDA,
+ 'GEOMETRY_INPUT_TYPE_ARB': 0x8DDB,
+ 'GEOMETRY_OUTPUT_TYPE_ARB': 0x8DDC,
+ 'MAX_GEOMETRY_VARYING_COMPONENTS_ARB': 0x8DDD,
+ 'MAX_VERTEX_VARYING_COMPONENTS_ARB': 0x8DDE,
+ 'MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB': 0x8DDF,
+ 'MAX_GEOMETRY_OUTPUT_VERTICES_ARB': 0x8DE0,
+ 'MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB': 0x8DE1,
+ 'HALF_FLOAT_ARB': 0x140B,
+ 'HALF_FLOAT': 0x140B,
+ 'CONSTANT_COLOR': 0x8001,
+ 'ONE_MINUS_CONSTANT_COLOR': 0x8002,
+ 'CONSTANT_ALPHA': 0x8003,
+ 'ONE_MINUS_CONSTANT_ALPHA': 0x8004,
+ 'BLEND_COLOR': 0x8005,
+ 'FUNC_ADD': 0x8006,
+ 'MIN': 0x8007,
+ 'MAX': 0x8008,
+ 'BLEND_EQUATION': 0x8009,
+ 'FUNC_SUBTRACT': 0x800A,
+ 'FUNC_REVERSE_SUBTRACT': 0x800B,
+ 'CONVOLUTION_1D': 0x8010,
+ 'CONVOLUTION_2D': 0x8011,
+ 'SEPARABLE_2D': 0x8012,
+ 'CONVOLUTION_BORDER_MODE': 0x8013,
+ 'CONVOLUTION_FILTER_SCALE': 0x8014,
+ 'CONVOLUTION_FILTER_BIAS': 0x8015,
+ 'REDUCE': 0x8016,
+ 'CONVOLUTION_FORMAT': 0x8017,
+ 'CONVOLUTION_WIDTH': 0x8018,
+ 'CONVOLUTION_HEIGHT': 0x8019,
+ 'MAX_CONVOLUTION_WIDTH': 0x801A,
+ 'MAX_CONVOLUTION_HEIGHT': 0x801B,
+ 'POST_CONVOLUTION_RED_SCALE': 0x801C,
+ 'POST_CONVOLUTION_GREEN_SCALE': 0x801D,
+ 'POST_CONVOLUTION_BLUE_SCALE': 0x801E,
+ 'POST_CONVOLUTION_ALPHA_SCALE': 0x801F,
+ 'POST_CONVOLUTION_RED_BIAS': 0x8020,
+ 'POST_CONVOLUTION_GREEN_BIAS': 0x8021,
+ 'POST_CONVOLUTION_BLUE_BIAS': 0x8022,
+ 'POST_CONVOLUTION_ALPHA_BIAS': 0x8023,
+ 'HISTOGRAM': 0x8024,
+ 'PROXY_HISTOGRAM': 0x8025,
+ 'HISTOGRAM_WIDTH': 0x8026,
+ 'HISTOGRAM_FORMAT': 0x8027,
+ 'HISTOGRAM_RED_SIZE': 0x8028,
+ 'HISTOGRAM_GREEN_SIZE': 0x8029,
+ 'HISTOGRAM_BLUE_SIZE': 0x802A,
+ 'HISTOGRAM_ALPHA_SIZE': 0x802B,
+ 'HISTOGRAM_LUMINANCE_SIZE': 0x802C,
+ 'HISTOGRAM_SINK': 0x802D,
+ 'MINMAX': 0x802E,
+ 'MINMAX_FORMAT': 0x802F,
+ 'MINMAX_SINK': 0x8030,
+ 'TABLE_TOO_LARGE': 0x8031,
+ 'COLOR_MATRIX': 0x80B1,
+ 'COLOR_MATRIX_STACK_DEPTH': 0x80B2,
+ 'MAX_COLOR_MATRIX_STACK_DEPTH': 0x80B3,
+ 'POST_COLOR_MATRIX_RED_SCALE': 0x80B4,
+ 'POST_COLOR_MATRIX_GREEN_SCALE': 0x80B5,
+ 'POST_COLOR_MATRIX_BLUE_SCALE': 0x80B6,
+ 'POST_COLOR_MATRIX_ALPHA_SCALE': 0x80B7,
+ 'POST_COLOR_MATRIX_RED_BIAS': 0x80B8,
+ 'POST_COLOR_MATRIX_GREEN_BIAS': 0x80B9,
+ 'POST_COLOR_MATRIX_BLUE_BIAS': 0x80BA,
+ 'POST_COLOR_MATRIX_ALPHA_BIAS': 0x80BB,
+ 'COLOR_TABLE': 0x80D0,
+ 'POST_CONVOLUTION_COLOR_TABLE': 0x80D1,
+ 'POST_COLOR_MATRIX_COLOR_TABLE': 0x80D2,
+ 'PROXY_COLOR_TABLE': 0x80D3,
+ 'PROXY_POST_CONVOLUTION_COLOR_TABLE': 0x80D4,
+ 'PROXY_POST_COLOR_MATRIX_COLOR_TABLE': 0x80D5,
+ 'COLOR_TABLE_SCALE': 0x80D6,
+ 'COLOR_TABLE_BIAS': 0x80D7,
+ 'COLOR_TABLE_FORMAT': 0x80D8,
+ 'COLOR_TABLE_WIDTH': 0x80D9,
+ 'COLOR_TABLE_RED_SIZE': 0x80DA,
+ 'COLOR_TABLE_GREEN_SIZE': 0x80DB,
+ 'COLOR_TABLE_BLUE_SIZE': 0x80DC,
+ 'COLOR_TABLE_ALPHA_SIZE': 0x80DD,
+ 'COLOR_TABLE_LUMINANCE_SIZE': 0x80DE,
+ 'COLOR_TABLE_INTENSITY_SIZE': 0x80DF,
+ 'IGNORE_BORDER': 0x8150,
+ 'CONSTANT_BORDER': 0x8151,
+ 'WRAP_BORDER': 0x8152,
+ 'REPLICATE_BORDER': 0x8153,
+ 'CONVOLUTION_BORDER_COLOR': 0x8154,
+ 'VERTEX_ATTRIB_ARRAY_DIVISOR_ARB': 0x88FE,
+ 'MAP_READ_BIT': 0x0001,
+ 'MAP_WRITE_BIT': 0x0002,
+ 'MAP_INVALIDATE_RANGE_BIT': 0x0004,
+ 'MAP_INVALIDATE_BUFFER_BIT': 0x0008,
+ 'MAP_FLUSH_EXPLICIT_BIT': 0x0010,
+ 'MAP_UNSYNCHRONIZED_BIT': 0x0020,
+ 'MATRIX_PALETTE_ARB': 0x8840,
+ 'MAX_MATRIX_PALETTE_STACK_DEPTH_ARB': 0x8841,
+ 'MAX_PALETTE_MATRICES_ARB': 0x8842,
+ 'CURRENT_PALETTE_MATRIX_ARB': 0x8843,
+ 'MATRIX_INDEX_ARRAY_ARB': 0x8844,
+ 'CURRENT_MATRIX_INDEX_ARB': 0x8845,
+ 'MATRIX_INDEX_ARRAY_SIZE_ARB': 0x8846,
+ 'MATRIX_INDEX_ARRAY_TYPE_ARB': 0x8847,
+ 'MATRIX_INDEX_ARRAY_STRIDE_ARB': 0x8848,
+ 'MATRIX_INDEX_ARRAY_POINTER_ARB': 0x8849,
+ 'MULTISAMPLE_ARB': 0x809D,
+ 'SAMPLE_ALPHA_TO_COVERAGE_ARB': 0x809E,
+ 'SAMPLE_ALPHA_TO_ONE_ARB': 0x809F,
+ 'SAMPLE_COVERAGE_ARB': 0x80A0,
+ 'SAMPLE_BUFFERS_ARB': 0x80A8,
+ 'SAMPLES_ARB': 0x80A9,
+ 'SAMPLE_COVERAGE_VALUE_ARB': 0x80AA,
+ 'SAMPLE_COVERAGE_INVERT_ARB': 0x80AB,
+ 'MULTISAMPLE_BIT_ARB': 0x20000000,
+ 'TEXTURE0_ARB': 0x84C0,
+ 'TEXTURE1_ARB': 0x84C1,
+ 'TEXTURE2_ARB': 0x84C2,
+ 'TEXTURE3_ARB': 0x84C3,
+ 'TEXTURE4_ARB': 0x84C4,
+ 'TEXTURE5_ARB': 0x84C5,
+ 'TEXTURE6_ARB': 0x84C6,
+ 'TEXTURE7_ARB': 0x84C7,
+ 'TEXTURE8_ARB': 0x84C8,
+ 'TEXTURE9_ARB': 0x84C9,
+ 'TEXTURE10_ARB': 0x84CA,
+ 'TEXTURE11_ARB': 0x84CB,
+ 'TEXTURE12_ARB': 0x84CC,
+ 'TEXTURE13_ARB': 0x84CD,
+ 'TEXTURE14_ARB': 0x84CE,
+ 'TEXTURE15_ARB': 0x84CF,
+ 'TEXTURE16_ARB': 0x84D0,
+ 'TEXTURE17_ARB': 0x84D1,
+ 'TEXTURE18_ARB': 0x84D2,
+ 'TEXTURE19_ARB': 0x84D3,
+ 'TEXTURE20_ARB': 0x84D4,
+ 'TEXTURE21_ARB': 0x84D5,
+ 'TEXTURE22_ARB': 0x84D6,
+ 'TEXTURE23_ARB': 0x84D7,
+ 'TEXTURE24_ARB': 0x84D8,
+ 'TEXTURE25_ARB': 0x84D9,
+ 'TEXTURE26_ARB': 0x84DA,
+ 'TEXTURE27_ARB': 0x84DB,
+ 'TEXTURE28_ARB': 0x84DC,
+ 'TEXTURE29_ARB': 0x84DD,
+ 'TEXTURE30_ARB': 0x84DE,
+ 'TEXTURE31_ARB': 0x84DF,
+ 'ACTIVE_TEXTURE_ARB': 0x84E0,
+ 'CLIENT_ACTIVE_TEXTURE_ARB': 0x84E1,
+ 'MAX_TEXTURE_UNITS_ARB': 0x84E2,
+ 'QUERY_COUNTER_BITS_ARB': 0x8864,
+ 'CURRENT_QUERY_ARB': 0x8865,
+ 'QUERY_RESULT_ARB': 0x8866,
+ 'QUERY_RESULT_AVAILABLE_ARB': 0x8867,
+ 'SAMPLES_PASSED_ARB': 0x8914,
+ 'PIXEL_PACK_BUFFER_ARB': 0x88EB,
+ 'PIXEL_UNPACK_BUFFER_ARB': 0x88EC,
+ 'PIXEL_PACK_BUFFER_BINDING_ARB': 0x88ED,
+ 'PIXEL_UNPACK_BUFFER_BINDING_ARB': 0x88EF,
+ 'POINT_SIZE_MIN_ARB': 0x8126,
+ 'POINT_SIZE_MAX_ARB': 0x8127,
+ 'POINT_FADE_THRESHOLD_SIZE_ARB': 0x8128,
+ 'POINT_DISTANCE_ATTENUATION_ARB': 0x8129,
+ 'POINT_SPRITE_ARB': 0x8861,
+ 'COORD_REPLACE_ARB': 0x8862,
+ 'PROGRAM_OBJECT_ARB': 0x8B40,
+ 'SHADER_OBJECT_ARB': 0x8B48,
+ 'OBJECT_TYPE_ARB': 0x8B4E,
+ 'OBJECT_SUBTYPE_ARB': 0x8B4F,
+ 'FLOAT_VEC2_ARB': 0x8B50,
+ 'FLOAT_VEC3_ARB': 0x8B51,
+ 'FLOAT_VEC4_ARB': 0x8B52,
+ 'INT_VEC2_ARB': 0x8B53,
+ 'INT_VEC3_ARB': 0x8B54,
+ 'INT_VEC4_ARB': 0x8B55,
+ 'BOOL_ARB': 0x8B56,
+ 'BOOL_VEC2_ARB': 0x8B57,
+ 'BOOL_VEC3_ARB': 0x8B58,
+ 'BOOL_VEC4_ARB': 0x8B59,
+ 'FLOAT_MAT2_ARB': 0x8B5A,
+ 'FLOAT_MAT3_ARB': 0x8B5B,
+ 'FLOAT_MAT4_ARB': 0x8B5C,
+ 'SAMPLER_1D_ARB': 0x8B5D,
+ 'SAMPLER_2D_ARB': 0x8B5E,
+ 'SAMPLER_3D_ARB': 0x8B5F,
+ 'SAMPLER_CUBE_ARB': 0x8B60,
+ 'SAMPLER_1D_SHADOW_ARB': 0x8B61,
+ 'SAMPLER_2D_SHADOW_ARB': 0x8B62,
+ 'SAMPLER_2D_RECT_ARB': 0x8B63,
+ 'SAMPLER_2D_RECT_SHADOW_ARB': 0x8B64,
+ 'OBJECT_DELETE_STATUS_ARB': 0x8B80,
+ 'OBJECT_COMPILE_STATUS_ARB': 0x8B81,
+ 'OBJECT_LINK_STATUS_ARB': 0x8B82,
+ 'OBJECT_VALIDATE_STATUS_ARB': 0x8B83,
+ 'OBJECT_INFO_LOG_LENGTH_ARB': 0x8B84,
+ 'OBJECT_ATTACHED_OBJECTS_ARB': 0x8B85,
+ 'OBJECT_ACTIVE_UNIFORMS_ARB': 0x8B86,
+ 'OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB': 0x8B87,
+ 'ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH': 0x8A35,
+ 'UNIFORM_NAME_LENGTH': 0x8A39,
+ 'UNIFORM_BLOCK_NAME_LENGTH': 0x8A41,
+ 'OBJECT_SHADER_SOURCE_LENGTH_ARB': 0x8B88,
+ 'SHADING_LANGUAGE_VERSION_ARB': 0x8B8C,
+ 'TEXTURE_COMPARE_MODE_ARB': 0x884C,
+ 'TEXTURE_COMPARE_FUNC_ARB': 0x884D,
+ 'COMPARE_R_TO_TEXTURE_ARB': 0x884E,
+ 'TEXTURE_COMPARE_FAIL_VALUE_ARB': 0x80BF,
+ 'CLAMP_TO_BORDER_ARB': 0x812D,
+ 'TEXTURE_BUFFER_ARB': 0x8C2A,
+ 'MAX_TEXTURE_BUFFER_SIZE_ARB': 0x8C2B,
+ 'TEXTURE_BINDING_BUFFER_ARB': 0x8C2C,
+ 'TEXTURE_BUFFER_DATA_STORE_BINDING_ARB': 0x8C2D,
+ 'TEXTURE_BUFFER_FORMAT_ARB': 0x8C2E,
+ 'COMPRESSED_ALPHA_ARB': 0x84E9,
+ 'COMPRESSED_LUMINANCE_ARB': 0x84EA,
+ 'COMPRESSED_LUMINANCE_ALPHA_ARB': 0x84EB,
+ 'COMPRESSED_INTENSITY_ARB': 0x84EC,
+ 'COMPRESSED_RGB_ARB': 0x84ED,
+ 'COMPRESSED_RGBA_ARB': 0x84EE,
+ 'TEXTURE_COMPRESSION_HINT_ARB': 0x84EF,
+ 'TEXTURE_COMPRESSED_IMAGE_SIZE_ARB': 0x86A0,
+ 'TEXTURE_COMPRESSED_ARB': 0x86A1,
+ 'NUM_COMPRESSED_TEXTURE_FORMATS_ARB': 0x86A2,
+ 'COMPRESSED_TEXTURE_FORMATS_ARB': 0x86A3,
+ 'COMPRESSED_RED_RGTC1': 0x8DBB,
+ 'COMPRESSED_SIGNED_RED_RGTC1': 0x8DBC,
+ 'COMPRESSED_RG_RGTC2': 0x8DBD,
+ 'COMPRESSED_SIGNED_RG_RGTC2': 0x8DBE,
+ 'NORMAL_MAP_ARB': 0x8511,
+ 'REFLECTION_MAP_ARB': 0x8512,
+ 'TEXTURE_CUBE_MAP_ARB': 0x8513,
+ 'TEXTURE_BINDING_CUBE_MAP_ARB': 0x8514,
+ 'TEXTURE_CUBE_MAP_POSITIVE_X_ARB': 0x8515,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_X_ARB': 0x8516,
+ 'TEXTURE_CUBE_MAP_POSITIVE_Y_ARB': 0x8517,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB': 0x8518,
+ 'TEXTURE_CUBE_MAP_POSITIVE_Z_ARB': 0x8519,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB': 0x851A,
+ 'PROXY_TEXTURE_CUBE_MAP_ARB': 0x851B,
+ 'MAX_CUBE_MAP_TEXTURE_SIZE_ARB': 0x851C,
+ 'SUBTRACT_ARB': 0x84E7,
+ 'COMBINE_ARB': 0x8570,
+ 'COMBINE_RGB_ARB': 0x8571,
+ 'COMBINE_ALPHA_ARB': 0x8572,
+ 'RGB_SCALE_ARB': 0x8573,
+ 'ADD_SIGNED_ARB': 0x8574,
+ 'INTERPOLATE_ARB': 0x8575,
+ 'CONSTANT_ARB': 0x8576,
+ 'PRIMARY_COLOR_ARB': 0x8577,
+ 'PREVIOUS_ARB': 0x8578,
+ 'SOURCE0_RGB_ARB': 0x8580,
+ 'SOURCE1_RGB_ARB': 0x8581,
+ 'SOURCE2_RGB_ARB': 0x8582,
+ 'SOURCE0_ALPHA_ARB': 0x8588,
+ 'SOURCE1_ALPHA_ARB': 0x8589,
+ 'SOURCE2_ALPHA_ARB': 0x858A,
+ 'OPERAND0_RGB_ARB': 0x8590,
+ 'OPERAND1_RGB_ARB': 0x8591,
+ 'OPERAND2_RGB_ARB': 0x8592,
+ 'OPERAND0_ALPHA_ARB': 0x8598,
+ 'OPERAND1_ALPHA_ARB': 0x8599,
+ 'OPERAND2_ALPHA_ARB': 0x859A,
+ 'DOT3_RGB_ARB': 0x86AE,
+ 'DOT3_RGBA_ARB': 0x86AF,
+ 'RGBA32F_ARB': 0x8814,
+ 'RGB32F_ARB': 0x8815,
+ 'ALPHA32F_ARB': 0x8816,
+ 'INTENSITY32F_ARB': 0x8817,
+ 'LUMINANCE32F_ARB': 0x8818,
+ 'LUMINANCE_ALPHA32F_ARB': 0x8819,
+ 'RGBA16F_ARB': 0x881A,
+ 'RGB16F_ARB': 0x881B,
+ 'ALPHA16F_ARB': 0x881C,
+ 'INTENSITY16F_ARB': 0x881D,
+ 'LUMINANCE16F_ARB': 0x881E,
+ 'LUMINANCE_ALPHA16F_ARB': 0x881F,
+ 'TEXTURE_RED_TYPE_ARB': 0x8C10,
+ 'TEXTURE_GREEN_TYPE_ARB': 0x8C11,
+ 'TEXTURE_BLUE_TYPE_ARB': 0x8C12,
+ 'TEXTURE_ALPHA_TYPE_ARB': 0x8C13,
+ 'TEXTURE_LUMINANCE_TYPE_ARB': 0x8C14,
+ 'TEXTURE_INTENSITY_TYPE_ARB': 0x8C15,
+ 'TEXTURE_DEPTH_TYPE_ARB': 0x8C16,
+ 'UNSIGNED_NORMALIZED_ARB': 0x8C17,
+ 'MIRRORED_REPEAT_ARB': 0x8370,
+ 'TEXTURE_RECTANGLE_ARB': 0x84F5,
+ 'TEXTURE_BINDING_RECTANGLE_ARB': 0x84F6,
+ 'PROXY_TEXTURE_RECTANGLE_ARB': 0x84F7,
+ 'MAX_RECTANGLE_TEXTURE_SIZE_ARB': 0x84F8,
+ 'SAMPLER_2D_RECT_ARB': 0x8B63,
+ 'SAMPLER_2D_RECT_SHADOW_ARB': 0x8B64,
+ 'RED': 0x1903,
+ 'RG': 0x8227,
+ 'RG_INTEGER': 0x8228,
+ 'R8': 0x8229,
+ 'R16': 0x822A,
+ 'RG8': 0x822B,
+ 'RG16': 0x822C,
+ 'R16F': 0x822D,
+ 'R32F': 0x822E,
+ 'RG16F': 0x822F,
+ 'RG32F': 0x8230,
+ 'R8I': 0x8231,
+ 'R8UI': 0x8232,
+ 'R16I': 0x8233,
+ 'R16UI': 0x8234,
+ 'R32I': 0x8235,
+ 'R32UI': 0x8236,
+ 'RG8I': 0x8237,
+ 'RG8UI': 0x8238,
+ 'RG16I': 0x8239,
+ 'RG16UI': 0x823A,
+ 'RG32I': 0x823B,
+ 'RG32UI': 0x823C,
+ 'TRANSPOSE_MODELVIEW_MATRIX_ARB': 0x84E3,
+ 'TRANSPOSE_PROJECTION_MATRIX_ARB': 0x84E4,
+ 'TRANSPOSE_TEXTURE_MATRIX_ARB': 0x84E5,
+ 'TRANSPOSE_COLOR_MATRIX_ARB': 0x84E6,
+ 'VERTEX_ARRAY_BINDING': 0x85B5,
+ 'MODELVIEW0_ARB': 0x1700,
+ 'MODELVIEW1_ARB': 0x850A,
+ 'MAX_VERTEX_UNITS_ARB': 0x86A4,
+ 'ACTIVE_VERTEX_UNITS_ARB': 0x86A5,
+ 'WEIGHT_SUM_UNITY_ARB': 0x86A6,
+ 'VERTEX_BLEND_ARB': 0x86A7,
+ 'CURRENT_WEIGHT_ARB': 0x86A8,
+ 'WEIGHT_ARRAY_TYPE_ARB': 0x86A9,
+ 'WEIGHT_ARRAY_STRIDE_ARB': 0x86AA,
+ 'WEIGHT_ARRAY_SIZE_ARB': 0x86AB,
+ 'WEIGHT_ARRAY_POINTER_ARB': 0x86AC,
+ 'WEIGHT_ARRAY_ARB': 0x86AD,
+ 'MODELVIEW2_ARB': 0x8722,
+ 'MODELVIEW3_ARB': 0x8723,
+ 'MODELVIEW4_ARB': 0x8724,
+ 'MODELVIEW5_ARB': 0x8725,
+ 'MODELVIEW6_ARB': 0x8726,
+ 'MODELVIEW7_ARB': 0x8727,
+ 'MODELVIEW8_ARB': 0x8728,
+ 'MODELVIEW9_ARB': 0x8729,
+ 'MODELVIEW10_ARB': 0x872A,
+ 'MODELVIEW11_ARB': 0x872B,
+ 'MODELVIEW12_ARB': 0x872C,
+ 'MODELVIEW13_ARB': 0x872D,
+ 'MODELVIEW14_ARB': 0x872E,
+ 'MODELVIEW15_ARB': 0x872F,
+ 'MODELVIEW16_ARB': 0x8730,
+ 'MODELVIEW17_ARB': 0x8731,
+ 'MODELVIEW18_ARB': 0x8732,
+ 'MODELVIEW19_ARB': 0x8733,
+ 'MODELVIEW20_ARB': 0x8734,
+ 'MODELVIEW21_ARB': 0x8735,
+ 'MODELVIEW22_ARB': 0x8736,
+ 'MODELVIEW23_ARB': 0x8737,
+ 'MODELVIEW24_ARB': 0x8738,
+ 'MODELVIEW25_ARB': 0x8739,
+ 'MODELVIEW26_ARB': 0x873A,
+ 'MODELVIEW27_ARB': 0x873B,
+ 'MODELVIEW28_ARB': 0x873C,
+ 'MODELVIEW29_ARB': 0x873D,
+ 'MODELVIEW30_ARB': 0x873E,
+ 'MODELVIEW31_ARB': 0x873F,
+ 'BUFFER_SIZE_ARB': 0x8764,
+ 'BUFFER_USAGE_ARB': 0x8765,
+ 'ARRAY_BUFFER_ARB': 0x8892,
+ 'ELEMENT_ARRAY_BUFFER_ARB': 0x8893,
+ 'ARRAY_BUFFER_BINDING_ARB': 0x8894,
+ 'ELEMENT_ARRAY_BUFFER_BINDING_ARB': 0x8895,
+ 'VERTEX_ARRAY_BUFFER_BINDING_ARB': 0x8896,
+ 'NORMAL_ARRAY_BUFFER_BINDING_ARB': 0x8897,
+ 'COLOR_ARRAY_BUFFER_BINDING_ARB': 0x8898,
+ 'INDEX_ARRAY_BUFFER_BINDING_ARB': 0x8899,
+ 'TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB': 0x889A,
+ 'EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB': 0x889B,
+ 'SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB': 0x889C,
+ 'FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB': 0x889D,
+ 'WEIGHT_ARRAY_BUFFER_BINDING_ARB': 0x889E,
+ 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB': 0x889F,
+ 'READ_ONLY_ARB': 0x88B8,
+ 'WRITE_ONLY_ARB': 0x88B9,
+ 'READ_WRITE_ARB': 0x88BA,
+ 'BUFFER_ACCESS_ARB': 0x88BB,
+ 'BUFFER_MAPPED_ARB': 0x88BC,
+ 'BUFFER_MAP_POINTER_ARB': 0x88BD,
+ 'STREAM_DRAW_ARB': 0x88E0,
+ 'STREAM_READ_ARB': 0x88E1,
+ 'STREAM_COPY_ARB': 0x88E2,
+ 'STATIC_DRAW_ARB': 0x88E4,
+ 'STATIC_READ_ARB': 0x88E5,
+ 'STATIC_COPY_ARB': 0x88E6,
+ 'DYNAMIC_DRAW_ARB': 0x88E8,
+ 'DYNAMIC_READ_ARB': 0x88E9,
+ 'DYNAMIC_COPY_ARB': 0x88EA,
+ 'COLOR_SUM_ARB': 0x8458,
+ 'VERTEX_PROGRAM_ARB': 0x8620,
+ 'VERTEX_ATTRIB_ARRAY_ENABLED_ARB': 0x8622,
+ 'VERTEX_ATTRIB_ARRAY_SIZE_ARB': 0x8623,
+ 'VERTEX_ATTRIB_ARRAY_STRIDE_ARB': 0x8624,
+ 'VERTEX_ATTRIB_ARRAY_TYPE_ARB': 0x8625,
+ 'CURRENT_VERTEX_ATTRIB_ARB': 0x8626,
+ 'PROGRAM_LENGTH_ARB': 0x8627,
+ 'PROGRAM_STRING_ARB': 0x8628,
+ 'MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB': 0x862E,
+ 'MAX_PROGRAM_MATRICES_ARB': 0x862F,
+ 'CURRENT_MATRIX_STACK_DEPTH_ARB': 0x8640,
+ 'CURRENT_MATRIX_ARB': 0x8641,
+ 'VERTEX_PROGRAM_POINT_SIZE_ARB': 0x8642,
+ 'VERTEX_PROGRAM_TWO_SIDE_ARB': 0x8643,
+ 'VERTEX_ATTRIB_ARRAY_POINTER_ARB': 0x8645,
+ 'PROGRAM_ERROR_POSITION_ARB': 0x864B,
+ 'PROGRAM_BINDING_ARB': 0x8677,
+ 'MAX_VERTEX_ATTRIBS_ARB': 0x8869,
+ 'VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB': 0x886A,
+ 'PROGRAM_ERROR_STRING_ARB': 0x8874,
+ 'PROGRAM_FORMAT_ASCII_ARB': 0x8875,
+ 'PROGRAM_FORMAT_ARB': 0x8876,
+ 'PROGRAM_INSTRUCTIONS_ARB': 0x88A0,
+ 'MAX_PROGRAM_INSTRUCTIONS_ARB': 0x88A1,
+ 'PROGRAM_NATIVE_INSTRUCTIONS_ARB': 0x88A2,
+ 'MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB': 0x88A3,
+ 'PROGRAM_TEMPORARIES_ARB': 0x88A4,
+ 'MAX_PROGRAM_TEMPORARIES_ARB': 0x88A5,
+ 'PROGRAM_NATIVE_TEMPORARIES_ARB': 0x88A6,
+ 'MAX_PROGRAM_NATIVE_TEMPORARIES_ARB': 0x88A7,
+ 'PROGRAM_PARAMETERS_ARB': 0x88A8,
+ 'MAX_PROGRAM_PARAMETERS_ARB': 0x88A9,
+ 'PROGRAM_NATIVE_PARAMETERS_ARB': 0x88AA,
+ 'MAX_PROGRAM_NATIVE_PARAMETERS_ARB': 0x88AB,
+ 'PROGRAM_ATTRIBS_ARB': 0x88AC,
+ 'MAX_PROGRAM_ATTRIBS_ARB': 0x88AD,
+ 'PROGRAM_NATIVE_ATTRIBS_ARB': 0x88AE,
+ 'MAX_PROGRAM_NATIVE_ATTRIBS_ARB': 0x88AF,
+ 'PROGRAM_ADDRESS_REGISTERS_ARB': 0x88B0,
+ 'MAX_PROGRAM_ADDRESS_REGISTERS_ARB': 0x88B1,
+ 'PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB': 0x88B2,
+ 'MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB': 0x88B3,
+ 'MAX_PROGRAM_LOCAL_PARAMETERS_ARB': 0x88B4,
+ 'MAX_PROGRAM_ENV_PARAMETERS_ARB': 0x88B5,
+ 'PROGRAM_UNDER_NATIVE_LIMITS_ARB': 0x88B6,
+ 'TRANSPOSE_CURRENT_MATRIX_ARB': 0x88B7,
+ 'MATRIX0_ARB': 0x88C0,
+ 'MATRIX1_ARB': 0x88C1,
+ 'MATRIX2_ARB': 0x88C2,
+ 'MATRIX3_ARB': 0x88C3,
+ 'MATRIX4_ARB': 0x88C4,
+ 'MATRIX5_ARB': 0x88C5,
+ 'MATRIX6_ARB': 0x88C6,
+ 'MATRIX7_ARB': 0x88C7,
+ 'MATRIX8_ARB': 0x88C8,
+ 'MATRIX9_ARB': 0x88C9,
+ 'MATRIX10_ARB': 0x88CA,
+ 'MATRIX11_ARB': 0x88CB,
+ 'MATRIX12_ARB': 0x88CC,
+ 'MATRIX13_ARB': 0x88CD,
+ 'MATRIX14_ARB': 0x88CE,
+ 'MATRIX15_ARB': 0x88CF,
+ 'MATRIX16_ARB': 0x88D0,
+ 'MATRIX17_ARB': 0x88D1,
+ 'MATRIX18_ARB': 0x88D2,
+ 'MATRIX19_ARB': 0x88D3,
+ 'MATRIX20_ARB': 0x88D4,
+ 'MATRIX21_ARB': 0x88D5,
+ 'MATRIX22_ARB': 0x88D6,
+ 'MATRIX23_ARB': 0x88D7,
+ 'MATRIX24_ARB': 0x88D8,
+ 'MATRIX25_ARB': 0x88D9,
+ 'MATRIX26_ARB': 0x88DA,
+ 'MATRIX27_ARB': 0x88DB,
+ 'MATRIX28_ARB': 0x88DC,
+ 'MATRIX29_ARB': 0x88DD,
+ 'MATRIX30_ARB': 0x88DE,
+ 'MATRIX31_ARB': 0x88DF,
+ 'VERTEX_SHADER_ARB': 0x8B31,
+ 'MAX_VERTEX_UNIFORM_COMPONENTS_ARB': 0x8B4A,
+ 'MAX_VARYING_FLOATS_ARB': 0x8B4B,
+ 'MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB': 0x8B4C,
+ 'MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB': 0x8B4D,
+ 'OBJECT_ACTIVE_ATTRIBUTES_ARB': 0x8B89,
+ 'OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB': 0x8B8A,
+ 'TEXTURE_POINT_MODE_ATIX': 0x60B0,
+ 'TEXTURE_POINT_ONE_COORD_ATIX': 0x60B1,
+ 'TEXTURE_POINT_SPRITE_ATIX': 0x60B2,
+ 'POINT_SPRITE_CULL_MODE_ATIX': 0x60B3,
+ 'POINT_SPRITE_CULL_CENTER_ATIX': 0x60B4,
+ 'POINT_SPRITE_CULL_CLIP_ATIX': 0x60B5,
+ 'MODULATE_ADD_ATIX': 0x8744,
+ 'MODULATE_SIGNED_ADD_ATIX': 0x8745,
+ 'MODULATE_SUBTRACT_ATIX': 0x8746,
+ 'SECONDARY_COLOR_ATIX': 0x8747,
+ 'TEXTURE_OUTPUT_RGB_ATIX': 0x8748,
+ 'TEXTURE_OUTPUT_ALPHA_ATIX': 0x8749,
+ 'OUTPUT_POINT_SIZE_ATIX': 0x610E,
+ 'MAX_DRAW_BUFFERS_ATI': 0x8824,
+ 'DRAW_BUFFER0_ATI': 0x8825,
+ 'DRAW_BUFFER1_ATI': 0x8826,
+ 'DRAW_BUFFER2_ATI': 0x8827,
+ 'DRAW_BUFFER3_ATI': 0x8828,
+ 'DRAW_BUFFER4_ATI': 0x8829,
+ 'DRAW_BUFFER5_ATI': 0x882A,
+ 'DRAW_BUFFER6_ATI': 0x882B,
+ 'DRAW_BUFFER7_ATI': 0x882C,
+ 'DRAW_BUFFER8_ATI': 0x882D,
+ 'DRAW_BUFFER9_ATI': 0x882E,
+ 'DRAW_BUFFER10_ATI': 0x882F,
+ 'DRAW_BUFFER11_ATI': 0x8830,
+ 'DRAW_BUFFER12_ATI': 0x8831,
+ 'DRAW_BUFFER13_ATI': 0x8832,
+ 'DRAW_BUFFER14_ATI': 0x8833,
+ 'DRAW_BUFFER15_ATI': 0x8834,
+ 'ELEMENT_ARRAY_ATI': 0x8768,
+ 'ELEMENT_ARRAY_TYPE_ATI': 0x8769,
+ 'ELEMENT_ARRAY_POINTER_ATI': 0x876A,
+ 'BUMP_ROT_MATRIX_ATI': 0x8775,
+ 'BUMP_ROT_MATRIX_SIZE_ATI': 0x8776,
+ 'BUMP_NUM_TEX_UNITS_ATI': 0x8777,
+ 'BUMP_TEX_UNITS_ATI': 0x8778,
+ 'DUDV_ATI': 0x8779,
+ 'DU8DV8_ATI': 0x877A,
+ 'BUMP_ENVMAP_ATI': 0x877B,
+ 'BUMP_TARGET_ATI': 0x877C,
+ 'RED_BIT_ATI': 0x00000001,
+ '2X_BIT_ATI': 0x00000001,
+ '4X_BIT_ATI': 0x00000002,
+ 'GREEN_BIT_ATI': 0x00000002,
+ 'COMP_BIT_ATI': 0x00000002,
+ 'BLUE_BIT_ATI': 0x00000004,
+ '8X_BIT_ATI': 0x00000004,
+ 'NEGATE_BIT_ATI': 0x00000004,
+ 'BIAS_BIT_ATI': 0x00000008,
+ 'HALF_BIT_ATI': 0x00000008,
+ 'QUARTER_BIT_ATI': 0x00000010,
+ 'EIGHTH_BIT_ATI': 0x00000020,
+ 'SATURATE_BIT_ATI': 0x00000040,
+ 'FRAGMENT_SHADER_ATI': 0x8920,
+ 'REG_0_ATI': 0x8921,
+ 'REG_1_ATI': 0x8922,
+ 'REG_2_ATI': 0x8923,
+ 'REG_3_ATI': 0x8924,
+ 'REG_4_ATI': 0x8925,
+ 'REG_5_ATI': 0x8926,
+ 'CON_0_ATI': 0x8941,
+ 'CON_1_ATI': 0x8942,
+ 'CON_2_ATI': 0x8943,
+ 'CON_3_ATI': 0x8944,
+ 'CON_4_ATI': 0x8945,
+ 'CON_5_ATI': 0x8946,
+ 'CON_6_ATI': 0x8947,
+ 'CON_7_ATI': 0x8948,
+ 'MOV_ATI': 0x8961,
+ 'ADD_ATI': 0x8963,
+ 'MUL_ATI': 0x8964,
+ 'SUB_ATI': 0x8965,
+ 'DOT3_ATI': 0x8966,
+ 'DOT4_ATI': 0x8967,
+ 'MAD_ATI': 0x8968,
+ 'LERP_ATI': 0x8969,
+ 'CND_ATI': 0x896A,
+ 'CND0_ATI': 0x896B,
+ 'DOT2_ADD_ATI': 0x896C,
+ 'SECONDARY_INTERPOLATOR_ATI': 0x896D,
+ 'NUM_FRAGMENT_REGISTERS_ATI': 0x896E,
+ 'NUM_FRAGMENT_CONSTANTS_ATI': 0x896F,
+ 'NUM_PASSES_ATI': 0x8970,
+ 'NUM_INSTRUCTIONS_PER_PASS_ATI': 0x8971,
+ 'NUM_INSTRUCTIONS_TOTAL_ATI': 0x8972,
+ 'NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI': 0x8973,
+ 'NUM_LOOPBACK_COMPONENTS_ATI': 0x8974,
+ 'COLOR_ALPHA_PAIRING_ATI': 0x8975,
+ 'SWIZZLE_STR_ATI': 0x8976,
+ 'SWIZZLE_STQ_ATI': 0x8977,
+ 'SWIZZLE_STR_DR_ATI': 0x8978,
+ 'SWIZZLE_STQ_DQ_ATI': 0x8979,
+ 'SWIZZLE_STRQ_ATI': 0x897A,
+ 'SWIZZLE_STRQ_DQ_ATI': 0x897B,
+ 'PN_TRIANGLES_ATI': 0x87F0,
+ 'MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI': 0x87F1,
+ 'PN_TRIANGLES_POINT_MODE_ATI': 0x87F2,
+ 'PN_TRIANGLES_NORMAL_MODE_ATI': 0x87F3,
+ 'PN_TRIANGLES_TESSELATION_LEVEL_ATI': 0x87F4,
+ 'PN_TRIANGLES_POINT_MODE_LINEAR_ATI': 0x87F5,
+ 'PN_TRIANGLES_POINT_MODE_CUBIC_ATI': 0x87F6,
+ 'PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI': 0x87F7,
+ 'PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI': 0x87F8,
+ 'STENCIL_BACK_FUNC_ATI': 0x8800,
+ 'STENCIL_BACK_FAIL_ATI': 0x8801,
+ 'STENCIL_BACK_PASS_DEPTH_FAIL_ATI': 0x8802,
+ 'STENCIL_BACK_PASS_DEPTH_PASS_ATI': 0x8803,
+ 'TEXT_FRAGMENT_SHADER_ATI': 0x8200,
+ 'COMPRESSED_LUMINANCE_ALPHA_3DC_ATI': 0x8837,
+ 'MODULATE_ADD_ATI': 0x8744,
+ 'MODULATE_SIGNED_ADD_ATI': 0x8745,
+ 'MODULATE_SUBTRACT_ATI': 0x8746,
+ 'RGBA_FLOAT32_ATI': 0x8814,
+ 'RGB_FLOAT32_ATI': 0x8815,
+ 'ALPHA_FLOAT32_ATI': 0x8816,
+ 'INTENSITY_FLOAT32_ATI': 0x8817,
+ 'LUMINANCE_FLOAT32_ATI': 0x8818,
+ 'LUMINANCE_ALPHA_FLOAT32_ATI': 0x8819,
+ 'RGBA_FLOAT16_ATI': 0x881A,
+ 'RGB_FLOAT16_ATI': 0x881B,
+ 'ALPHA_FLOAT16_ATI': 0x881C,
+ 'INTENSITY_FLOAT16_ATI': 0x881D,
+ 'LUMINANCE_FLOAT16_ATI': 0x881E,
+ 'LUMINANCE_ALPHA_FLOAT16_ATI': 0x881F,
+ 'MIRROR_CLAMP_ATI': 0x8742,
+ 'MIRROR_CLAMP_TO_EDGE_ATI': 0x8743,
+ 'STATIC_ATI': 0x8760,
+ 'DYNAMIC_ATI': 0x8761,
+ 'PRESERVE_ATI': 0x8762,
+ 'DISCARD_ATI': 0x8763,
+ 'OBJECT_BUFFER_SIZE_ATI': 0x8764,
+ 'OBJECT_BUFFER_USAGE_ATI': 0x8765,
+ 'ARRAY_OBJECT_BUFFER_ATI': 0x8766,
+ 'ARRAY_OBJECT_OFFSET_ATI': 0x8767,
+ 'MAX_VERTEX_STREAMS_ATI': 0x876B,
+ 'VERTEX_SOURCE_ATI': 0x876C,
+ 'VERTEX_STREAM0_ATI': 0x876D,
+ 'VERTEX_STREAM1_ATI': 0x876E,
+ 'VERTEX_STREAM2_ATI': 0x876F,
+ 'VERTEX_STREAM3_ATI': 0x8770,
+ 'VERTEX_STREAM4_ATI': 0x8771,
+ 'VERTEX_STREAM5_ATI': 0x8772,
+ 'VERTEX_STREAM6_ATI': 0x8773,
+ 'VERTEX_STREAM7_ATI': 0x8774,
+ '422_EXT': 0x80CC,
+ '422_REV_EXT': 0x80CD,
+ '422_AVERAGE_EXT': 0x80CE,
+ '422_REV_AVERAGE_EXT': 0x80CF,
+ 'CG_VERTEX_SHADER_EXT': 0x890E,
+ 'CG_FRAGMENT_SHADER_EXT': 0x890F,
+ 'ABGR_EXT': 0x8000,
+ 'BGR_EXT': 0x80E0,
+ 'BGRA_EXT': 0x80E1,
+ 'MAX_VERTEX_BINDABLE_UNIFORMS_EXT': 0x8DE2,
+ 'MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT': 0x8DE3,
+ 'MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT': 0x8DE4,
+ 'MAX_BINDABLE_UNIFORM_SIZE_EXT': 0x8DED,
+ 'UNIFORM_BUFFER_EXT': 0x8DEE,
+ 'UNIFORM_BUFFER_BINDING_EXT': 0x8DEF,
+ 'CONSTANT_COLOR_EXT': 0x8001,
+ 'ONE_MINUS_CONSTANT_COLOR_EXT': 0x8002,
+ 'CONSTANT_ALPHA_EXT': 0x8003,
+ 'ONE_MINUS_CONSTANT_ALPHA_EXT': 0x8004,
+ 'BLEND_COLOR_EXT': 0x8005,
+ 'BLEND_EQUATION_RGB_EXT': 0x8009,
+ 'BLEND_EQUATION_ALPHA_EXT': 0x883D,
+ 'BLEND_DST_RGB_EXT': 0x80C8,
+ 'BLEND_SRC_RGB_EXT': 0x80C9,
+ 'BLEND_DST_ALPHA_EXT': 0x80CA,
+ 'BLEND_SRC_ALPHA_EXT': 0x80CB,
+ 'FUNC_ADD_EXT': 0x8006,
+ 'MIN_EXT': 0x8007,
+ 'MAX_EXT': 0x8008,
+ 'BLEND_EQUATION_EXT': 0x8009,
+ 'FUNC_SUBTRACT_EXT': 0x800A,
+ 'FUNC_REVERSE_SUBTRACT_EXT': 0x800B,
+ 'CLIP_VOLUME_CLIPPING_HINT_EXT': 0x80F0,
+ 'CMYK_EXT': 0x800C,
+ 'CMYKA_EXT': 0x800D,
+ 'PACK_CMYK_HINT_EXT': 0x800E,
+ 'UNPACK_CMYK_HINT_EXT': 0x800F,
+ 'ARRAY_ELEMENT_LOCK_FIRST_EXT': 0x81A8,
+ 'ARRAY_ELEMENT_LOCK_COUNT_EXT': 0x81A9,
+ 'CONVOLUTION_1D_EXT': 0x8010,
+ 'CONVOLUTION_2D_EXT': 0x8011,
+ 'SEPARABLE_2D_EXT': 0x8012,
+ 'CONVOLUTION_BORDER_MODE_EXT': 0x8013,
+ 'CONVOLUTION_FILTER_SCALE_EXT': 0x8014,
+ 'CONVOLUTION_FILTER_BIAS_EXT': 0x8015,
+ 'REDUCE_EXT': 0x8016,
+ 'CONVOLUTION_FORMAT_EXT': 0x8017,
+ 'CONVOLUTION_WIDTH_EXT': 0x8018,
+ 'CONVOLUTION_HEIGHT_EXT': 0x8019,
+ 'MAX_CONVOLUTION_WIDTH_EXT': 0x801A,
+ 'MAX_CONVOLUTION_HEIGHT_EXT': 0x801B,
+ 'POST_CONVOLUTION_RED_SCALE_EXT': 0x801C,
+ 'POST_CONVOLUTION_GREEN_SCALE_EXT': 0x801D,
+ 'POST_CONVOLUTION_BLUE_SCALE_EXT': 0x801E,
+ 'POST_CONVOLUTION_ALPHA_SCALE_EXT': 0x801F,
+ 'POST_CONVOLUTION_RED_BIAS_EXT': 0x8020,
+ 'POST_CONVOLUTION_GREEN_BIAS_EXT': 0x8021,
+ 'POST_CONVOLUTION_BLUE_BIAS_EXT': 0x8022,
+ 'POST_CONVOLUTION_ALPHA_BIAS_EXT': 0x8023,
+ 'TANGENT_ARRAY_EXT': 0x8439,
+ 'BINORMAL_ARRAY_EXT': 0x843A,
+ 'CURRENT_TANGENT_EXT': 0x843B,
+ 'CURRENT_BINORMAL_EXT': 0x843C,
+ 'TANGENT_ARRAY_TYPE_EXT': 0x843E,
+ 'TANGENT_ARRAY_STRIDE_EXT': 0x843F,
+ 'BINORMAL_ARRAY_TYPE_EXT': 0x8440,
+ 'BINORMAL_ARRAY_STRIDE_EXT': 0x8441,
+ 'TANGENT_ARRAY_POINTER_EXT': 0x8442,
+ 'BINORMAL_ARRAY_POINTER_EXT': 0x8443,
+ 'MAP1_TANGENT_EXT': 0x8444,
+ 'MAP2_TANGENT_EXT': 0x8445,
+ 'MAP1_BINORMAL_EXT': 0x8446,
+ 'MAP2_BINORMAL_EXT': 0x8447,
+ 'DEPTH_BOUNDS_TEST_EXT': 0x8890,
+ 'DEPTH_BOUNDS_EXT': 0x8891,
+ 'PROGRAM_MATRIX_EXT': 0x8E2D,
+ 'TRANSPOSE_PROGRAM_MATRIX_EXT': 0x8E2E,
+ 'PROGRAM_MATRIX_STACK_DEPTH_EXT': 0x8E2F,
+ 'MAX_ELEMENTS_VERTICES': 0x80E8,
+ 'MAX_ELEMENTS_INDICES': 0x80E9,
+ 'FOG_COORDINATE_SOURCE_EXT': 0x8450,
+ 'FOG_COORDINATE_EXT': 0x8451,
+ 'FRAGMENT_DEPTH_EXT': 0x8452,
+ 'CURRENT_FOG_COORDINATE_EXT': 0x8453,
+ 'FOG_COORDINATE_ARRAY_TYPE_EXT': 0x8454,
+ 'FOG_COORDINATE_ARRAY_STRIDE_EXT': 0x8455,
+ 'FOG_COORDINATE_ARRAY_POINTER_EXT': 0x8456,
+ 'FOG_COORDINATE_ARRAY_EXT': 0x8457,
+ 'FRAGMENT_LIGHTING_EXT': 0x8400,
+ 'FRAGMENT_COLOR_MATERIAL_EXT': 0x8401,
+ 'FRAGMENT_COLOR_MATERIAL_FACE_EXT': 0x8402,
+ 'FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT': 0x8403,
+ 'MAX_FRAGMENT_LIGHTS_EXT': 0x8404,
+ 'MAX_ACTIVE_LIGHTS_EXT': 0x8405,
+ 'CURRENT_RASTER_NORMAL_EXT': 0x8406,
+ 'LIGHT_ENV_MODE_EXT': 0x8407,
+ 'FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT': 0x8408,
+ 'FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT': 0x8409,
+ 'FRAGMENT_LIGHT_MODEL_AMBIENT_EXT': 0x840A,
+ 'FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT': 0x840B,
+ 'FRAGMENT_LIGHT0_EXT': 0x840C,
+ 'FRAGMENT_LIGHT7_EXT': 0x8413,
+ 'DRAW_FRAMEBUFFER_BINDING_EXT': 0x8CA6,
+ 'READ_FRAMEBUFFER_EXT': 0x8CA8,
+ 'DRAW_FRAMEBUFFER_EXT': 0x8CA9,
+ 'READ_FRAMEBUFFER_BINDING_EXT': 0x8CAA,
+ 'RENDERBUFFER_SAMPLES_EXT': 0x8CAB,
+ 'FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT': 0x8D56,
+ 'MAX_SAMPLES_EXT': 0x8D57,
+ 'INVALID_FRAMEBUFFER_OPERATION_EXT': 0x0506,
+ 'MAX_RENDERBUFFER_SIZE_EXT': 0x84E8,
+ 'FRAMEBUFFER_BINDING_EXT': 0x8CA6,
+ 'RENDERBUFFER_BINDING_EXT': 0x8CA7,
+ 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT': 0x8CD0,
+ 'FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT': 0x8CD1,
+ 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT': 0x8CD2,
+ 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT': 0x8CD3,
+ 'FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT': 0x8CD4,
+ 'FRAMEBUFFER_COMPLETE_EXT': 0x8CD5,
+ 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT': 0x8CD6,
+ 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT': 0x8CD7,
+ 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT': 0x8CD9,
+ 'FRAMEBUFFER_INCOMPLETE_FORMATS_EXT': 0x8CDA,
+ 'FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT': 0x8CDB,
+ 'FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT': 0x8CDC,
+ 'FRAMEBUFFER_UNSUPPORTED_EXT': 0x8CDD,
+ 'MAX_COLOR_ATTACHMENTS_EXT': 0x8CDF,
+ 'COLOR_ATTACHMENT0_EXT': 0x8CE0,
+ 'COLOR_ATTACHMENT1_EXT': 0x8CE1,
+ 'COLOR_ATTACHMENT2_EXT': 0x8CE2,
+ 'COLOR_ATTACHMENT3_EXT': 0x8CE3,
+ 'COLOR_ATTACHMENT4_EXT': 0x8CE4,
+ 'COLOR_ATTACHMENT5_EXT': 0x8CE5,
+ 'COLOR_ATTACHMENT6_EXT': 0x8CE6,
+ 'COLOR_ATTACHMENT7_EXT': 0x8CE7,
+ 'COLOR_ATTACHMENT8_EXT': 0x8CE8,
+ 'COLOR_ATTACHMENT9_EXT': 0x8CE9,
+ 'COLOR_ATTACHMENT10_EXT': 0x8CEA,
+ 'COLOR_ATTACHMENT11_EXT': 0x8CEB,
+ 'COLOR_ATTACHMENT12_EXT': 0x8CEC,
+ 'COLOR_ATTACHMENT13_EXT': 0x8CED,
+ 'COLOR_ATTACHMENT14_EXT': 0x8CEE,
+ 'COLOR_ATTACHMENT15_EXT': 0x8CEF,
+ 'DEPTH_ATTACHMENT_EXT': 0x8D00,
+ 'STENCIL_ATTACHMENT_EXT': 0x8D20,
+ 'FRAMEBUFFER_EXT': 0x8D40,
+ 'RENDERBUFFER_EXT': 0x8D41,
+ 'RENDERBUFFER_WIDTH_EXT': 0x8D42,
+ 'RENDERBUFFER_HEIGHT_EXT': 0x8D43,
+ 'RENDERBUFFER_INTERNAL_FORMAT_EXT': 0x8D44,
+ 'STENCIL_INDEX1_EXT': 0x8D46,
+ 'STENCIL_INDEX4_EXT': 0x8D47,
+ 'STENCIL_INDEX8_EXT': 0x8D48,
+ 'STENCIL_INDEX16_EXT': 0x8D49,
+ 'RENDERBUFFER_RED_SIZE_EXT': 0x8D50,
+ 'RENDERBUFFER_GREEN_SIZE_EXT': 0x8D51,
+ 'RENDERBUFFER_BLUE_SIZE_EXT': 0x8D52,
+ 'RENDERBUFFER_ALPHA_SIZE_EXT': 0x8D53,
+ 'RENDERBUFFER_DEPTH_SIZE_EXT': 0x8D54,
+ 'RENDERBUFFER_STENCIL_SIZE_EXT': 0x8D55,
+ 'FRAMEBUFFER_SRGB_EXT': 0x8DB9,
+ 'FRAMEBUFFER_SRGB_CAPABLE_EXT': 0x8DBA,
+ 'LINES_ADJACENCY_EXT': 0xA,
+ 'LINE_STRIP_ADJACENCY_EXT': 0xB,
+ 'TRIANGLES_ADJACENCY_EXT': 0xC,
+ 'TRIANGLE_STRIP_ADJACENCY_EXT': 0xD,
+ 'PROGRAM_POINT_SIZE_EXT': 0x8642,
+ 'MAX_VARYING_COMPONENTS_EXT': 0x8B4B,
+ 'MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT': 0x8C29,
+ 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT': 0x8CD4,
+ 'FRAMEBUFFER_ATTACHMENT_LAYERED_EXT': 0x8DA7,
+ 'FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT': 0x8DA8,
+ 'FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT': 0x8DA9,
+ 'GEOMETRY_SHADER_EXT': 0x8DD9,
+ 'GEOMETRY_VERTICES_OUT_EXT': 0x8DDA,
+ 'GEOMETRY_INPUT_TYPE_EXT': 0x8DDB,
+ 'GEOMETRY_OUTPUT_TYPE_EXT': 0x8DDC,
+ 'MAX_GEOMETRY_VARYING_COMPONENTS_EXT': 0x8DDD,
+ 'MAX_VERTEX_VARYING_COMPONENTS_EXT': 0x8DDE,
+ 'MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT': 0x8DDF,
+ 'MAX_GEOMETRY_OUTPUT_VERTICES_EXT': 0x8DE0,
+ 'MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT': 0x8DE1,
+ 'VERTEX_ATTRIB_ARRAY_INTEGER_EXT': 0x88FD,
+ 'SAMPLER_1D_ARRAY_EXT': 0x8DC0,
+ 'SAMPLER_2D_ARRAY_EXT': 0x8DC1,
+ 'SAMPLER_BUFFER_EXT': 0x8DC2,
+ 'SAMPLER_1D_ARRAY_SHADOW_EXT': 0x8DC3,
+ 'SAMPLER_2D_ARRAY_SHADOW_EXT': 0x8DC4,
+ 'SAMPLER_CUBE_SHADOW_EXT': 0x8DC5,
+ 'UNSIGNED_INT_VEC2_EXT': 0x8DC6,
+ 'UNSIGNED_INT_VEC3_EXT': 0x8DC7,
+ 'UNSIGNED_INT_VEC4_EXT': 0x8DC8,
+ 'INT_SAMPLER_1D_EXT': 0x8DC9,
+ 'INT_SAMPLER_2D_EXT': 0x8DCA,
+ 'INT_SAMPLER_3D_EXT': 0x8DCB,
+ 'INT_SAMPLER_CUBE_EXT': 0x8DCC,
+ 'INT_SAMPLER_2D_RECT_EXT': 0x8DCD,
+ 'INT_SAMPLER_1D_ARRAY_EXT': 0x8DCE,
+ 'INT_SAMPLER_2D_ARRAY_EXT': 0x8DCF,
+ 'INT_SAMPLER_BUFFER_EXT': 0x8DD0,
+ 'UNSIGNED_INT_SAMPLER_1D_EXT': 0x8DD1,
+ 'UNSIGNED_INT_SAMPLER_2D_EXT': 0x8DD2,
+ 'UNSIGNED_INT_SAMPLER_3D_EXT': 0x8DD3,
+ 'UNSIGNED_INT_SAMPLER_CUBE_EXT': 0x8DD4,
+ 'UNSIGNED_INT_SAMPLER_2D_RECT_EXT': 0x8DD5,
+ 'UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT': 0x8DD6,
+ 'UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT': 0x8DD7,
+ 'UNSIGNED_INT_SAMPLER_BUFFER_EXT': 0x8DD8,
+ 'HISTOGRAM_EXT': 0x8024,
+ 'PROXY_HISTOGRAM_EXT': 0x8025,
+ 'HISTOGRAM_WIDTH_EXT': 0x8026,
+ 'HISTOGRAM_FORMAT_EXT': 0x8027,
+ 'HISTOGRAM_RED_SIZE_EXT': 0x8028,
+ 'HISTOGRAM_GREEN_SIZE_EXT': 0x8029,
+ 'HISTOGRAM_BLUE_SIZE_EXT': 0x802A,
+ 'HISTOGRAM_ALPHA_SIZE_EXT': 0x802B,
+ 'HISTOGRAM_LUMINANCE_SIZE_EXT': 0x802C,
+ 'HISTOGRAM_SINK_EXT': 0x802D,
+ 'MINMAX_EXT': 0x802E,
+ 'MINMAX_FORMAT_EXT': 0x802F,
+ 'MINMAX_SINK_EXT': 0x8030,
+ 'FRAGMENT_MATERIAL_EXT': 0x8349,
+ 'FRAGMENT_NORMAL_EXT': 0x834A,
+ 'FRAGMENT_COLOR_EXT': 0x834C,
+ 'ATTENUATION_EXT': 0x834D,
+ 'SHADOW_ATTENUATION_EXT': 0x834E,
+ 'TEXTURE_APPLICATION_MODE_EXT': 0x834F,
+ 'TEXTURE_LIGHT_EXT': 0x8350,
+ 'TEXTURE_MATERIAL_FACE_EXT': 0x8351,
+ 'TEXTURE_MATERIAL_PARAMETER_EXT': 0x8352,
+ 'FRAGMENT_DEPTH_EXT': 0x8452,
+ 'MULTISAMPLE_EXT': 0x809D,
+ 'SAMPLE_ALPHA_TO_MASK_EXT': 0x809E,
+ 'SAMPLE_ALPHA_TO_ONE_EXT': 0x809F,
+ 'SAMPLE_MASK_EXT': 0x80A0,
+ '1PASS_EXT': 0x80A1,
+ '2PASS_0_EXT': 0x80A2,
+ '2PASS_1_EXT': 0x80A3,
+ '4PASS_0_EXT': 0x80A4,
+ '4PASS_1_EXT': 0x80A5,
+ '4PASS_2_EXT': 0x80A6,
+ '4PASS_3_EXT': 0x80A7,
+ 'SAMPLE_BUFFERS_EXT': 0x80A8,
+ 'SAMPLES_EXT': 0x80A9,
+ 'SAMPLE_MASK_VALUE_EXT': 0x80AA,
+ 'SAMPLE_MASK_INVERT_EXT': 0x80AB,
+ 'SAMPLE_PATTERN_EXT': 0x80AC,
+ 'MULTISAMPLE_BIT_EXT': 0x20000000,
+ 'DEPTH_STENCIL_EXT': 0x84F9,
+ 'UNSIGNED_INT_24_8_EXT': 0x84FA,
+ 'DEPTH24_STENCIL8_EXT': 0x88F0,
+ 'TEXTURE_STENCIL_SIZE_EXT': 0x88F1,
+ 'R11F_G11F_B10F_EXT': 0x8C3A,
+ 'UNSIGNED_INT_10F_11F_11F_REV_EXT': 0x8C3B,
+ 'RGBA_SIGNED_COMPONENTS_EXT': 0x8C3C,
+ 'UNSIGNED_BYTE_3_3_2_EXT': 0x8032,
+ 'UNSIGNED_SHORT_4_4_4_4_EXT': 0x8033,
+ 'UNSIGNED_SHORT_5_5_5_1_EXT': 0x8034,
+ 'UNSIGNED_INT_8_8_8_8_EXT': 0x8035,
+ 'UNSIGNED_INT_10_10_10_2_EXT': 0x8036,
+ 'TEXTURE_1D': 0x0DE0,
+ 'TEXTURE_2D': 0x0DE1,
+ 'PROXY_TEXTURE_1D': 0x8063,
+ 'PROXY_TEXTURE_2D': 0x8064,
+ 'TEXTURE_3D_EXT': 0x806F,
+ 'PROXY_TEXTURE_3D_EXT': 0x8070,
+ 'COLOR_TABLE_FORMAT_EXT': 0x80D8,
+ 'COLOR_TABLE_WIDTH_EXT': 0x80D9,
+ 'COLOR_TABLE_RED_SIZE_EXT': 0x80DA,
+ 'COLOR_TABLE_GREEN_SIZE_EXT': 0x80DB,
+ 'COLOR_TABLE_BLUE_SIZE_EXT': 0x80DC,
+ 'COLOR_TABLE_ALPHA_SIZE_EXT': 0x80DD,
+ 'COLOR_TABLE_LUMINANCE_SIZE_EXT': 0x80DE,
+ 'COLOR_TABLE_INTENSITY_SIZE_EXT': 0x80DF,
+ 'COLOR_INDEX1_EXT': 0x80E2,
+ 'COLOR_INDEX2_EXT': 0x80E3,
+ 'COLOR_INDEX4_EXT': 0x80E4,
+ 'COLOR_INDEX8_EXT': 0x80E5,
+ 'COLOR_INDEX12_EXT': 0x80E6,
+ 'COLOR_INDEX16_EXT': 0x80E7,
+ 'TEXTURE_INDEX_SIZE_EXT': 0x80ED,
+ 'TEXTURE_CUBE_MAP_ARB': 0x8513,
+ 'PROXY_TEXTURE_CUBE_MAP_ARB': 0x851B,
+ 'PIXEL_PACK_BUFFER_EXT': 0x88EB,
+ 'PIXEL_UNPACK_BUFFER_EXT': 0x88EC,
+ 'PIXEL_PACK_BUFFER_BINDING_EXT': 0x88ED,
+ 'PIXEL_UNPACK_BUFFER_BINDING_EXT': 0x88EF,
+ 'PIXEL_TRANSFORM_2D_EXT': 0x8330,
+ 'PIXEL_MAG_FILTER_EXT': 0x8331,
+ 'PIXEL_MIN_FILTER_EXT': 0x8332,
+ 'PIXEL_CUBIC_WEIGHT_EXT': 0x8333,
+ 'CUBIC_EXT': 0x8334,
+ 'AVERAGE_EXT': 0x8335,
+ 'PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT': 0x8336,
+ 'MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT': 0x8337,
+ 'PIXEL_TRANSFORM_2D_MATRIX_EXT': 0x8338,
+ 'POINT_SIZE_MIN_EXT': 0x8126,
+ 'POINT_SIZE_MAX_EXT': 0x8127,
+ 'POINT_FADE_THRESHOLD_SIZE_EXT': 0x8128,
+ 'DISTANCE_ATTENUATION_EXT': 0x8129,
+ 'POLYGON_OFFSET_EXT': 0x8037,
+ 'POLYGON_OFFSET_FACTOR_EXT': 0x8038,
+ 'POLYGON_OFFSET_BIAS_EXT': 0x8039,
+ 'RESCALE_NORMAL_EXT': 0x803A,
+ 'COLOR_SUM_EXT': 0x8458,
+ 'CURRENT_SECONDARY_COLOR_EXT': 0x8459,
+ 'SECONDARY_COLOR_ARRAY_SIZE_EXT': 0x845A,
+ 'SECONDARY_COLOR_ARRAY_TYPE_EXT': 0x845B,
+ 'SECONDARY_COLOR_ARRAY_STRIDE_EXT': 0x845C,
+ 'SECONDARY_COLOR_ARRAY_POINTER_EXT': 0x845D,
+ 'SECONDARY_COLOR_ARRAY_EXT': 0x845E,
+ 'LIGHT_MODEL_COLOR_CONTROL_EXT': 0x81F8,
+ 'SINGLE_COLOR_EXT': 0x81F9,
+ 'SEPARATE_SPECULAR_COLOR_EXT': 0x81FA,
+ 'SHARED_TEXTURE_PALETTE_EXT': 0x81FB,
+ 'STENCIL_TAG_BITS_EXT': 0x88F2,
+ 'STENCIL_CLEAR_TAG_VALUE_EXT': 0x88F3,
+ 'STENCIL_TEST_TWO_SIDE_EXT': 0x8910,
+ 'ACTIVE_STENCIL_FACE_EXT': 0x8911,
+ 'INCR_WRAP_EXT': 0x8507,
+ 'DECR_WRAP_EXT': 0x8508,
+ 'ALPHA4_EXT': 0x803B,
+ 'ALPHA8_EXT': 0x803C,
+ 'ALPHA12_EXT': 0x803D,
+ 'ALPHA16_EXT': 0x803E,
+ 'LUMINANCE4_EXT': 0x803F,
+ 'LUMINANCE8_EXT': 0x8040,
+ 'LUMINANCE12_EXT': 0x8041,
+ 'LUMINANCE16_EXT': 0x8042,
+ 'LUMINANCE4_ALPHA4_EXT': 0x8043,
+ 'LUMINANCE6_ALPHA2_EXT': 0x8044,
+ 'LUMINANCE8_ALPHA8_EXT': 0x8045,
+ 'LUMINANCE12_ALPHA4_EXT': 0x8046,
+ 'LUMINANCE12_ALPHA12_EXT': 0x8047,
+ 'LUMINANCE16_ALPHA16_EXT': 0x8048,
+ 'INTENSITY_EXT': 0x8049,
+ 'INTENSITY4_EXT': 0x804A,
+ 'INTENSITY8_EXT': 0x804B,
+ 'INTENSITY12_EXT': 0x804C,
+ 'INTENSITY16_EXT': 0x804D,
+ 'RGB2_EXT': 0x804E,
+ 'RGB4_EXT': 0x804F,
+ 'RGB5_EXT': 0x8050,
+ 'RGB8_EXT': 0x8051,
+ 'RGB10_EXT': 0x8052,
+ 'RGB12_EXT': 0x8053,
+ 'RGB16_EXT': 0x8054,
+ 'RGBA2_EXT': 0x8055,
+ 'RGBA4_EXT': 0x8056,
+ 'RGB5_A1_EXT': 0x8057,
+ 'RGBA8_EXT': 0x8058,
+ 'RGB10_A2_EXT': 0x8059,
+ 'RGBA12_EXT': 0x805A,
+ 'RGBA16_EXT': 0x805B,
+ 'TEXTURE_RED_SIZE_EXT': 0x805C,
+ 'TEXTURE_GREEN_SIZE_EXT': 0x805D,
+ 'TEXTURE_BLUE_SIZE_EXT': 0x805E,
+ 'TEXTURE_ALPHA_SIZE_EXT': 0x805F,
+ 'TEXTURE_LUMINANCE_SIZE_EXT': 0x8060,
+ 'TEXTURE_INTENSITY_SIZE_EXT': 0x8061,
+ 'REPLACE_EXT': 0x8062,
+ 'PROXY_TEXTURE_1D_EXT': 0x8063,
+ 'PROXY_TEXTURE_2D_EXT': 0x8064,
+ 'PACK_SKIP_IMAGES_EXT': 0x806B,
+ 'PACK_IMAGE_HEIGHT_EXT': 0x806C,
+ 'UNPACK_SKIP_IMAGES_EXT': 0x806D,
+ 'UNPACK_IMAGE_HEIGHT_EXT': 0x806E,
+ 'TEXTURE_3D_EXT': 0x806F,
+ 'PROXY_TEXTURE_3D_EXT': 0x8070,
+ 'TEXTURE_DEPTH_EXT': 0x8071,
+ 'TEXTURE_WRAP_R_EXT': 0x8072,
+ 'MAX_3D_TEXTURE_SIZE_EXT': 0x8073,
+ 'COMPARE_REF_DEPTH_TO_TEXTURE_EXT': 0x884E,
+ 'MAX_ARRAY_TEXTURE_LAYERS_EXT': 0x88FF,
+ 'TEXTURE_1D_ARRAY_EXT': 0x8C18,
+ 'PROXY_TEXTURE_1D_ARRAY_EXT': 0x8C19,
+ 'TEXTURE_2D_ARRAY_EXT': 0x8C1A,
+ 'PROXY_TEXTURE_2D_ARRAY_EXT': 0x8C1B,
+ 'TEXTURE_BINDING_1D_ARRAY_EXT': 0x8C1C,
+ 'TEXTURE_BINDING_2D_ARRAY_EXT': 0x8C1D,
+ 'TEXTURE_BUFFER_EXT': 0x8C2A,
+ 'MAX_TEXTURE_BUFFER_SIZE_EXT': 0x8C2B,
+ 'TEXTURE_BINDING_BUFFER_EXT': 0x8C2C,
+ 'TEXTURE_BUFFER_DATA_STORE_BINDING_EXT': 0x8C2D,
+ 'TEXTURE_BUFFER_FORMAT_EXT': 0x8C2E,
+ 'COMPRESSED_RGB_S3TC_DXT1_EXT': 0x83F0,
+ 'COMPRESSED_RGBA_S3TC_DXT1_EXT': 0x83F1,
+ 'COMPRESSED_LUMINANCE_LATC1_EXT': 0x8C70,
+ 'COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT': 0x8C71,
+ 'COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT': 0x8C72,
+ 'COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT': 0x8C73,
+ 'COMPRESSED_RED_RGTC1_EXT': 0x8DBB,
+ 'COMPRESSED_SIGNED_RED_RGTC1_EXT': 0x8DBC,
+ 'COMPRESSED_RED_GREEN_RGTC2_EXT': 0x8DBD,
+ 'COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT': 0x8DBE,
+ 'COMPRESSED_RGB_S3TC_DXT1_EXT': 0x83F0,
+ 'COMPRESSED_RGBA_S3TC_DXT1_EXT': 0x83F1,
+ 'COMPRESSED_RGBA_S3TC_DXT3_EXT': 0x83F2,
+ 'COMPRESSED_RGBA_S3TC_DXT5_EXT': 0x83F3,
+ 'NORMAL_MAP_EXT': 0x8511,
+ 'REFLECTION_MAP_EXT': 0x8512,
+ 'TEXTURE_CUBE_MAP_EXT': 0x8513,
+ 'TEXTURE_BINDING_CUBE_MAP_EXT': 0x8514,
+ 'TEXTURE_CUBE_MAP_POSITIVE_X_EXT': 0x8515,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_X_EXT': 0x8516,
+ 'TEXTURE_CUBE_MAP_POSITIVE_Y_EXT': 0x8517,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT': 0x8518,
+ 'TEXTURE_CUBE_MAP_POSITIVE_Z_EXT': 0x8519,
+ 'TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT': 0x851A,
+ 'PROXY_TEXTURE_CUBE_MAP_EXT': 0x851B,
+ 'MAX_CUBE_MAP_TEXTURE_SIZE_EXT': 0x851C,
+ 'CLAMP_TO_EDGE_EXT': 0x812F,
+ 'COMBINE_EXT': 0x8570,
+ 'COMBINE_RGB_EXT': 0x8571,
+ 'COMBINE_ALPHA_EXT': 0x8572,
+ 'RGB_SCALE_EXT': 0x8573,
+ 'ADD_SIGNED_EXT': 0x8574,
+ 'INTERPOLATE_EXT': 0x8575,
+ 'CONSTANT_EXT': 0x8576,
+ 'PRIMARY_COLOR_EXT': 0x8577,
+ 'PREVIOUS_EXT': 0x8578,
+ 'SOURCE0_RGB_EXT': 0x8580,
+ 'SOURCE1_RGB_EXT': 0x8581,
+ 'SOURCE2_RGB_EXT': 0x8582,
+ 'SOURCE0_ALPHA_EXT': 0x8588,
+ 'SOURCE1_ALPHA_EXT': 0x8589,
+ 'SOURCE2_ALPHA_EXT': 0x858A,
+ 'OPERAND0_RGB_EXT': 0x8590,
+ 'OPERAND1_RGB_EXT': 0x8591,
+ 'OPERAND2_RGB_EXT': 0x8592,
+ 'OPERAND0_ALPHA_EXT': 0x8598,
+ 'OPERAND1_ALPHA_EXT': 0x8599,
+ 'OPERAND2_ALPHA_EXT': 0x859A,
+ 'DOT3_RGB_EXT': 0x8740,
+ 'DOT3_RGBA_EXT': 0x8741,
+ 'TEXTURE_MAX_ANISOTROPY_EXT': 0x84FE,
+ 'MAX_TEXTURE_MAX_ANISOTROPY_EXT': 0x84FF,
+ 'RGBA32UI_EXT': 0x8D70,
+ 'RGB32UI_EXT': 0x8D71,
+ 'ALPHA32UI_EXT': 0x8D72,
+ 'INTENSITY32UI_EXT': 0x8D73,
+ 'LUMINANCE32UI_EXT': 0x8D74,
+ 'LUMINANCE_ALPHA32UI_EXT': 0x8D75,
+ 'RGBA16UI_EXT': 0x8D76,
+ 'RGB16UI_EXT': 0x8D77,
+ 'ALPHA16UI_EXT': 0x8D78,
+ 'INTENSITY16UI_EXT': 0x8D79,
+ 'LUMINANCE16UI_EXT': 0x8D7A,
+ 'LUMINANCE_ALPHA16UI_EXT': 0x8D7B,
+ 'RGBA8UI_EXT': 0x8D7C,
+ 'RGB8UI_EXT': 0x8D7D,
+ 'ALPHA8UI_EXT': 0x8D7E,
+ 'INTENSITY8UI_EXT': 0x8D7F,
+ 'LUMINANCE8UI_EXT': 0x8D80,
+ 'LUMINANCE_ALPHA8UI_EXT': 0x8D81,
+ 'RGBA32I_EXT': 0x8D82,
+ 'RGB32I_EXT': 0x8D83,
+ 'ALPHA32I_EXT': 0x8D84,
+ 'INTENSITY32I_EXT': 0x8D85,
+ 'LUMINANCE32I_EXT': 0x8D86,
+ 'LUMINANCE_ALPHA32I_EXT': 0x8D87,
+ 'RGBA16I_EXT': 0x8D88,
+ 'RGB16I_EXT': 0x8D89,
+ 'ALPHA16I_EXT': 0x8D8A,
+ 'INTENSITY16I_EXT': 0x8D8B,
+ 'LUMINANCE16I_EXT': 0x8D8C,
+ 'LUMINANCE_ALPHA16I_EXT': 0x8D8D,
+ 'RGBA8I_EXT': 0x8D8E,
+ 'RGB8I_EXT': 0x8D8F,
+ 'ALPHA8I_EXT': 0x8D90,
+ 'INTENSITY8I_EXT': 0x8D91,
+ 'LUMINANCE8I_EXT': 0x8D92,
+ 'LUMINANCE_ALPHA8I_EXT': 0x8D93,
+ 'RED_INTEGER_EXT': 0x8D94,
+ 'GREEN_INTEGER_EXT': 0x8D95,
+ 'BLUE_INTEGER_EXT': 0x8D96,
+ 'ALPHA_INTEGER_EXT': 0x8D97,
+ 'RGB_INTEGER_EXT': 0x8D98,
+ 'RGBA_INTEGER_EXT': 0x8D99,
+ 'BGR_INTEGER_EXT': 0x8D9A,
+ 'BGRA_INTEGER_EXT': 0x8D9B,
+ 'LUMINANCE_INTEGER_EXT': 0x8D9C,
+ 'LUMINANCE_ALPHA_INTEGER_EXT': 0x8D9D,
+ 'RGBA_INTEGER_MODE_EXT': 0x8D9E,
+ 'MAX_TEXTURE_LOD_BIAS_EXT': 0x84FD,
+ 'TEXTURE_FILTER_CONTROL_EXT': 0x8500,
+ 'TEXTURE_LOD_BIAS_EXT': 0x8501,
+ 'MIRROR_CLAMP_EXT': 0x8742,
+ 'MIRROR_CLAMP_TO_EDGE_EXT': 0x8743,
+ 'MIRROR_CLAMP_TO_BORDER_EXT': 0x8912,
+ 'TEXTURE_PRIORITY_EXT': 0x8066,
+ 'TEXTURE_RESIDENT_EXT': 0x8067,
+ 'TEXTURE_1D_BINDING_EXT': 0x8068,
+ 'TEXTURE_2D_BINDING_EXT': 0x8069,
+ 'TEXTURE_3D_BINDING_EXT': 0x806A,
+ 'PERTURB_EXT': 0x85AE,
+ 'TEXTURE_NORMAL_EXT': 0x85AF,
+ 'TEXTURE_RECTANGLE_EXT': 0x84F5,
+ 'TEXTURE_BINDING_RECTANGLE_EXT': 0x84F6,
+ 'PROXY_TEXTURE_RECTANGLE_EXT': 0x84F7,
+ 'MAX_RECTANGLE_TEXTURE_SIZE_EXT': 0x84F8,
+ 'SRGB_EXT': 0x8C40,
+ 'SRGB8_EXT': 0x8C41,
+ 'SRGB_ALPHA_EXT': 0x8C42,
+ 'SRGB8_ALPHA8_EXT': 0x8C43,
+ 'SLUMINANCE_ALPHA_EXT': 0x8C44,
+ 'SLUMINANCE8_ALPHA8_EXT': 0x8C45,
+ 'SLUMINANCE_EXT': 0x8C46,
+ 'SLUMINANCE8_EXT': 0x8C47,
+ 'COMPRESSED_SRGB_EXT': 0x8C48,
+ 'COMPRESSED_SRGB_ALPHA_EXT': 0x8C49,
+ 'COMPRESSED_SLUMINANCE_EXT': 0x8C4A,
+ 'COMPRESSED_SLUMINANCE_ALPHA_EXT': 0x8C4B,
+ 'COMPRESSED_SRGB_S3TC_DXT1_EXT': 0x8C4C,
+ 'COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT': 0x8C4D,
+ 'COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT': 0x8C4E,
+ 'COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT': 0x8C4F,
+ 'RGB9_E5_EXT': 0x8C3D,
+ 'UNSIGNED_INT_5_9_9_9_REV_EXT': 0x8C3E,
+ 'TEXTURE_SHARED_SIZE_EXT': 0x8C3F,
+ 'TEXTURE_SWIZZLE_R_EXT': 0x8E42,
+ 'TEXTURE_SWIZZLE_G_EXT': 0x8E43,
+ 'TEXTURE_SWIZZLE_B_EXT': 0x8E44,
+ 'TEXTURE_SWIZZLE_A_EXT': 0x8E45,
+ 'TEXTURE_SWIZZLE_RGBA_EXT': 0x8E46,
+ 'TIME_ELAPSED_EXT': 0x88BF,
+ 'TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT': 0x8C76,
+ 'TRANSFORM_FEEDBACK_BUFFER_MODE_EXT': 0x8C7F,
+ 'MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT': 0x8C80,
+ 'TRANSFORM_FEEDBACK_VARYINGS_EXT': 0x8C83,
+ 'TRANSFORM_FEEDBACK_BUFFER_START_EXT': 0x8C84,
+ 'TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT': 0x8C85,
+ 'PRIMITIVES_GENERATED_EXT': 0x8C87,
+ 'TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT': 0x8C88,
+ 'RASTERIZER_DISCARD_EXT': 0x8C89,
+ 'MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT': 0x8C8A,
+ 'MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT': 0x8C8B,
+ 'INTERLEAVED_ATTRIBS_EXT': 0x8C8C,
+ 'SEPARATE_ATTRIBS_EXT': 0x8C8D,
+ 'TRANSFORM_FEEDBACK_BUFFER_EXT': 0x8C8E,
+ 'TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT': 0x8C8F,
+ 'DOUBLE_EXT': 0x140A,
+ 'VERTEX_ARRAY_EXT': 0x8074,
+ 'NORMAL_ARRAY_EXT': 0x8075,
+ 'COLOR_ARRAY_EXT': 0x8076,
+ 'INDEX_ARRAY_EXT': 0x8077,
+ 'TEXTURE_COORD_ARRAY_EXT': 0x8078,
+ 'EDGE_FLAG_ARRAY_EXT': 0x8079,
+ 'VERTEX_ARRAY_SIZE_EXT': 0x807A,
+ 'VERTEX_ARRAY_TYPE_EXT': 0x807B,
+ 'VERTEX_ARRAY_STRIDE_EXT': 0x807C,
+ 'VERTEX_ARRAY_COUNT_EXT': 0x807D,
+ 'NORMAL_ARRAY_TYPE_EXT': 0x807E,
+ 'NORMAL_ARRAY_STRIDE_EXT': 0x807F,
+ 'NORMAL_ARRAY_COUNT_EXT': 0x8080,
+ 'COLOR_ARRAY_SIZE_EXT': 0x8081,
+ 'COLOR_ARRAY_TYPE_EXT': 0x8082,
+ 'COLOR_ARRAY_STRIDE_EXT': 0x8083,
+ 'COLOR_ARRAY_COUNT_EXT': 0x8084,
+ 'INDEX_ARRAY_TYPE_EXT': 0x8085,
+ 'INDEX_ARRAY_STRIDE_EXT': 0x8086,
+ 'INDEX_ARRAY_COUNT_EXT': 0x8087,
+ 'TEXTURE_COORD_ARRAY_SIZE_EXT': 0x8088,
+ 'TEXTURE_COORD_ARRAY_TYPE_EXT': 0x8089,
+ 'TEXTURE_COORD_ARRAY_STRIDE_EXT': 0x808A,
+ 'TEXTURE_COORD_ARRAY_COUNT_EXT': 0x808B,
+ 'EDGE_FLAG_ARRAY_STRIDE_EXT': 0x808C,
+ 'EDGE_FLAG_ARRAY_COUNT_EXT': 0x808D,
+ 'VERTEX_ARRAY_POINTER_EXT': 0x808E,
+ 'NORMAL_ARRAY_POINTER_EXT': 0x808F,
+ 'COLOR_ARRAY_POINTER_EXT': 0x8090,
+ 'INDEX_ARRAY_POINTER_EXT': 0x8091,
+ 'TEXTURE_COORD_ARRAY_POINTER_EXT': 0x8092,
+ 'EDGE_FLAG_ARRAY_POINTER_EXT': 0x8093,
+ 'BGRA': 0x80E1,
+ 'VERTEX_SHADER_EXT': 0x8780,
+ 'VERTEX_SHADER_BINDING_EXT': 0x8781,
+ 'OP_INDEX_EXT': 0x8782,
+ 'OP_NEGATE_EXT': 0x8783,
+ 'OP_DOT3_EXT': 0x8784,
+ 'OP_DOT4_EXT': 0x8785,
+ 'OP_MUL_EXT': 0x8786,
+ 'OP_ADD_EXT': 0x8787,
+ 'OP_MADD_EXT': 0x8788,
+ 'OP_FRAC_EXT': 0x8789,
+ 'OP_MAX_EXT': 0x878A,
+ 'OP_MIN_EXT': 0x878B,
+ 'OP_SET_GE_EXT': 0x878C,
+ 'OP_SET_LT_EXT': 0x878D,
+ 'OP_CLAMP_EXT': 0x878E,
+ 'OP_FLOOR_EXT': 0x878F,
+ 'OP_ROUND_EXT': 0x8790,
+ 'OP_EXP_BASE_2_EXT': 0x8791,
+ 'OP_LOG_BASE_2_EXT': 0x8792,
+ 'OP_POWER_EXT': 0x8793,
+ 'OP_RECIP_EXT': 0x8794,
+ 'OP_RECIP_SQRT_EXT': 0x8795,
+ 'OP_SUB_EXT': 0x8796,
+ 'OP_CROSS_PRODUCT_EXT': 0x8797,
+ 'OP_MULTIPLY_MATRIX_EXT': 0x8798,
+ 'OP_MOV_EXT': 0x8799,
+ 'OUTPUT_VERTEX_EXT': 0x879A,
+ 'OUTPUT_COLOR0_EXT': 0x879B,
+ 'OUTPUT_COLOR1_EXT': 0x879C,
+ 'OUTPUT_TEXTURE_COORD0_EXT': 0x879D,
+ 'OUTPUT_TEXTURE_COORD1_EXT': 0x879E,
+ 'OUTPUT_TEXTURE_COORD2_EXT': 0x879F,
+ 'OUTPUT_TEXTURE_COORD3_EXT': 0x87A0,
+ 'OUTPUT_TEXTURE_COORD4_EXT': 0x87A1,
+ 'OUTPUT_TEXTURE_COORD5_EXT': 0x87A2,
+ 'OUTPUT_TEXTURE_COORD6_EXT': 0x87A3,
+ 'OUTPUT_TEXTURE_COORD7_EXT': 0x87A4,
+ 'OUTPUT_TEXTURE_COORD8_EXT': 0x87A5,
+ 'OUTPUT_TEXTURE_COORD9_EXT': 0x87A6,
+ 'OUTPUT_TEXTURE_COORD10_EXT': 0x87A7,
+ 'OUTPUT_TEXTURE_COORD11_EXT': 0x87A8,
+ 'OUTPUT_TEXTURE_COORD12_EXT': 0x87A9,
+ 'OUTPUT_TEXTURE_COORD13_EXT': 0x87AA,
+ 'OUTPUT_TEXTURE_COORD14_EXT': 0x87AB,
+ 'OUTPUT_TEXTURE_COORD15_EXT': 0x87AC,
+ 'OUTPUT_TEXTURE_COORD16_EXT': 0x87AD,
+ 'OUTPUT_TEXTURE_COORD17_EXT': 0x87AE,
+ 'OUTPUT_TEXTURE_COORD18_EXT': 0x87AF,
+ 'OUTPUT_TEXTURE_COORD19_EXT': 0x87B0,
+ 'OUTPUT_TEXTURE_COORD20_EXT': 0x87B1,
+ 'OUTPUT_TEXTURE_COORD21_EXT': 0x87B2,
+ 'OUTPUT_TEXTURE_COORD22_EXT': 0x87B3,
+ 'OUTPUT_TEXTURE_COORD23_EXT': 0x87B4,
+ 'OUTPUT_TEXTURE_COORD24_EXT': 0x87B5,
+ 'OUTPUT_TEXTURE_COORD25_EXT': 0x87B6,
+ 'OUTPUT_TEXTURE_COORD26_EXT': 0x87B7,
+ 'OUTPUT_TEXTURE_COORD27_EXT': 0x87B8,
+ 'OUTPUT_TEXTURE_COORD28_EXT': 0x87B9,
+ 'OUTPUT_TEXTURE_COORD29_EXT': 0x87BA,
+ 'OUTPUT_TEXTURE_COORD30_EXT': 0x87BB,
+ 'OUTPUT_TEXTURE_COORD31_EXT': 0x87BC,
+ 'OUTPUT_FOG_EXT': 0x87BD,
+ 'SCALAR_EXT': 0x87BE,
+ 'VECTOR_EXT': 0x87BF,
+ 'MATRIX_EXT': 0x87C0,
+ 'VARIANT_EXT': 0x87C1,
+ 'INVARIANT_EXT': 0x87C2,
+ 'LOCAL_CONSTANT_EXT': 0x87C3,
+ 'LOCAL_EXT': 0x87C4,
+ 'MAX_VERTEX_SHADER_INSTRUCTIONS_EXT': 0x87C5,
+ 'MAX_VERTEX_SHADER_VARIANTS_EXT': 0x87C6,
+ 'MAX_VERTEX_SHADER_INVARIANTS_EXT': 0x87C7,
+ 'MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT': 0x87C8,
+ 'MAX_VERTEX_SHADER_LOCALS_EXT': 0x87C9,
+ 'MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT': 0x87CA,
+ 'MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT': 0x87CB,
+ 'MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT': 0x87CC,
+ 'MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT': 0x87CD,
+ 'MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT': 0x87CE,
+ 'VERTEX_SHADER_INSTRUCTIONS_EXT': 0x87CF,
+ 'VERTEX_SHADER_VARIANTS_EXT': 0x87D0,
+ 'VERTEX_SHADER_INVARIANTS_EXT': 0x87D1,
+ 'VERTEX_SHADER_LOCAL_CONSTANTS_EXT': 0x87D2,
+ 'VERTEX_SHADER_LOCALS_EXT': 0x87D3,
+ 'VERTEX_SHADER_OPTIMIZED_EXT': 0x87D4,
+ 'X_EXT': 0x87D5,
+ 'Y_EXT': 0x87D6,
+ 'Z_EXT': 0x87D7,
+ 'W_EXT': 0x87D8,
+ 'NEGATIVE_X_EXT': 0x87D9,
+ 'NEGATIVE_Y_EXT': 0x87DA,
+ 'NEGATIVE_Z_EXT': 0x87DB,
+ 'NEGATIVE_W_EXT': 0x87DC,
+ 'ZERO_EXT': 0x87DD,
+ 'ONE_EXT': 0x87DE,
+ 'NEGATIVE_ONE_EXT': 0x87DF,
+ 'NORMALIZED_RANGE_EXT': 0x87E0,
+ 'FULL_RANGE_EXT': 0x87E1,
+ 'CURRENT_VERTEX_EXT': 0x87E2,
+ 'MVP_MATRIX_EXT': 0x87E3,
+ 'VARIANT_VALUE_EXT': 0x87E4,
+ 'VARIANT_DATATYPE_EXT': 0x87E5,
+ 'VARIANT_ARRAY_STRIDE_EXT': 0x87E6,
+ 'VARIANT_ARRAY_TYPE_EXT': 0x87E7,
+ 'VARIANT_ARRAY_EXT': 0x87E8,
+ 'VARIANT_ARRAY_POINTER_EXT': 0x87E9,
+ 'INVARIANT_VALUE_EXT': 0x87EA,
+ 'INVARIANT_DATATYPE_EXT': 0x87EB,
+ 'LOCAL_CONSTANT_VALUE_EXT': 0x87EC,
+ 'LOCAL_CONSTANT_DATATYPE_EXT': 0x87ED,
+ 'MODELVIEW0_STACK_DEPTH_EXT': 0x0BA3,
+ 'MODELVIEW0_MATRIX_EXT': 0x0BA6,
+ 'MODELVIEW0_EXT': 0x1700,
+ 'MODELVIEW1_STACK_DEPTH_EXT': 0x8502,
+ 'MODELVIEW1_MATRIX_EXT': 0x8506,
+ 'VERTEX_WEIGHTING_EXT': 0x8509,
+ 'MODELVIEW1_EXT': 0x850A,
+ 'CURRENT_VERTEX_WEIGHT_EXT': 0x850B,
+ 'VERTEX_WEIGHT_ARRAY_EXT': 0x850C,
+ 'VERTEX_WEIGHT_ARRAY_SIZE_EXT': 0x850D,
+ 'VERTEX_WEIGHT_ARRAY_TYPE_EXT': 0x850E,
+ 'VERTEX_WEIGHT_ARRAY_STRIDE_EXT': 0x850F,
+ 'VERTEX_WEIGHT_ARRAY_POINTER_EXT': 0x8510,
+ 'OCCLUSION_TEST_HP': 0x8165,
+ 'OCCLUSION_TEST_RESULT_HP': 0x8166,
+ 'MIRRORED_REPEAT_IBM': 0x8370,
+ 'RED_MIN_CLAMP_INGR': 0x8560,
+ 'GREEN_MIN_CLAMP_INGR': 0x8561,
+ 'BLUE_MIN_CLAMP_INGR': 0x8562,
+ 'ALPHA_MIN_CLAMP_INGR': 0x8563,
+ 'RED_MAX_CLAMP_INGR': 0x8564,
+ 'GREEN_MAX_CLAMP_INGR': 0x8565,
+ 'BLUE_MAX_CLAMP_INGR': 0x8566,
+ 'ALPHA_MAX_CLAMP_INGR': 0x8567,
+ 'INTERLACE_READ_INGR': 0x8568,
+ 'PARALLEL_ARRAYS_INTEL': 0x83F4,
+ 'VERTEX_ARRAY_PARALLEL_POINTERS_INTEL': 0x83F5,
+ 'NORMAL_ARRAY_PARALLEL_POINTERS_INTEL': 0x83F6,
+ 'COLOR_ARRAY_PARALLEL_POINTERS_INTEL': 0x83F7,
+ 'TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL': 0x83F8,
+ 'KTX_FRONT_REGION': 0x0,
+ 'KTX_BACK_REGION': 0x1,
+ 'KTX_Z_REGION': 0x2,
+ 'KTX_STENCIL_REGION': 0x3,
+ 'TEXTURE_1D_STACK_MESAX': 0x8759,
+ 'TEXTURE_2D_STACK_MESAX': 0x875A,
+ 'PROXY_TEXTURE_1D_STACK_MESAX': 0x875B,
+ 'PROXY_TEXTURE_2D_STACK_MESAX': 0x875C,
+ 'TEXTURE_1D_STACK_BINDING_MESAX': 0x875D,
+ 'TEXTURE_2D_STACK_BINDING_MESAX': 0x875E,
+ 'PACK_INVERT_MESA': 0x8758,
+ 'UNSIGNED_SHORT_8_8_MESA': 0x85BA,
+ 'UNSIGNED_SHORT_8_8_REV_MESA': 0x85BB,
+ 'YCBCR_MESA': 0x8757,
+ 'QUERY_WAIT_NV': 0x8E13,
+ 'QUERY_NO_WAIT_NV': 0x8E14,
+ 'QUERY_BY_REGION_WAIT_NV': 0x8E15,
+ 'QUERY_BY_REGION_NO_WAIT_NV': 0x8E16,
+ 'DEPTH_STENCIL_TO_RGBA_NV': 0x886E,
+ 'DEPTH_STENCIL_TO_BGRA_NV': 0x886F,
+ 'DEPTH_COMPONENT32F_NV': 0x8DAB,
+ 'DEPTH32F_STENCIL8_NV': 0x8DAC,
+ 'FLOAT_32_UNSIGNED_INT_24_8_REV_NV': 0x8DAD,
+ 'DEPTH_BUFFER_FLOAT_MODE_NV': 0x8DAF,
+ 'DEPTH_CLAMP_NV': 0x864F,
+ 'SAMPLE_COUNT_BITS_NV': 0x8864,
+ 'CURRENT_SAMPLE_COUNT_QUERY_NV': 0x8865,
+ 'QUERY_RESULT_NV': 0x8866,
+ 'QUERY_RESULT_AVAILABLE_NV': 0x8867,
+ 'SAMPLE_COUNT_NV': 0x8914,
+ 'EVAL_2D_NV': 0x86C0,
+ 'EVAL_TRIANGULAR_2D_NV': 0x86C1,
+ 'MAP_TESSELLATION_NV': 0x86C2,
+ 'MAP_ATTRIB_U_ORDER_NV': 0x86C3,
+ 'MAP_ATTRIB_V_ORDER_NV': 0x86C4,
+ 'EVAL_FRACTIONAL_TESSELLATION_NV': 0x86C5,
+ 'EVAL_VERTEX_ATTRIB0_NV': 0x86C6,
+ 'EVAL_VERTEX_ATTRIB1_NV': 0x86C7,
+ 'EVAL_VERTEX_ATTRIB2_NV': 0x86C8,
+ 'EVAL_VERTEX_ATTRIB3_NV': 0x86C9,
+ 'EVAL_VERTEX_ATTRIB4_NV': 0x86CA,
+ 'EVAL_VERTEX_ATTRIB5_NV': 0x86CB,
+ 'EVAL_VERTEX_ATTRIB6_NV': 0x86CC,
+ 'EVAL_VERTEX_ATTRIB7_NV': 0x86CD,
+ 'EVAL_VERTEX_ATTRIB8_NV': 0x86CE,
+ 'EVAL_VERTEX_ATTRIB9_NV': 0x86CF,
+ 'EVAL_VERTEX_ATTRIB10_NV': 0x86D0,
+ 'EVAL_VERTEX_ATTRIB11_NV': 0x86D1,
+ 'EVAL_VERTEX_ATTRIB12_NV': 0x86D2,
+ 'EVAL_VERTEX_ATTRIB13_NV': 0x86D3,
+ 'EVAL_VERTEX_ATTRIB14_NV': 0x86D4,
+ 'EVAL_VERTEX_ATTRIB15_NV': 0x86D5,
+ 'MAX_MAP_TESSELLATION_NV': 0x86D6,
+ 'MAX_RATIONAL_EVAL_ORDER_NV': 0x86D7,
+ 'SAMPLE_POSITION_NV': 0x8E50,
+ 'SAMPLE_MASK_NV': 0x8E51,
+ 'SAMPLE_MASK_VALUE_NV': 0x8E52,
+ 'TEXTURE_BINDING_RENDERBUFFER_NV': 0x8E53,
+ 'TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV': 0x8E54,
+ 'TEXTURE_RENDERBUFFER_NV': 0x8E55,
+ 'SAMPLER_RENDERBUFFER_NV': 0x8E56,
+ 'INT_SAMPLER_RENDERBUFFER_NV': 0x8E57,
+ 'UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV': 0x8E58,
+ 'MAX_SAMPLE_MASK_WORDS_NV': 0x8E59,
+ 'ALL_COMPLETED_NV': 0x84F2,
+ 'FENCE_STATUS_NV': 0x84F3,
+ 'FENCE_CONDITION_NV': 0x84F4,
+ 'FLOAT_R_NV': 0x8880,
+ 'FLOAT_RG_NV': 0x8881,
+ 'FLOAT_RGB_NV': 0x8882,
+ 'FLOAT_RGBA_NV': 0x8883,
+ 'FLOAT_R16_NV': 0x8884,
+ 'FLOAT_R32_NV': 0x8885,
+ 'FLOAT_RG16_NV': 0x8886,
+ 'FLOAT_RG32_NV': 0x8887,
+ 'FLOAT_RGB16_NV': 0x8888,
+ 'FLOAT_RGB32_NV': 0x8889,
+ 'FLOAT_RGBA16_NV': 0x888A,
+ 'FLOAT_RGBA32_NV': 0x888B,
+ 'TEXTURE_FLOAT_COMPONENTS_NV': 0x888C,
+ 'FLOAT_CLEAR_COLOR_VALUE_NV': 0x888D,
+ 'FLOAT_RGBA_MODE_NV': 0x888E,
+ 'FOG_DISTANCE_MODE_NV': 0x855A,
+ 'EYE_RADIAL_NV': 0x855B,
+ 'EYE_PLANE_ABSOLUTE_NV': 0x855C,
+ 'MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV': 0x8868,
+ 'FRAGMENT_PROGRAM_NV': 0x8870,
+ 'MAX_TEXTURE_COORDS_NV': 0x8871,
+ 'MAX_TEXTURE_IMAGE_UNITS_NV': 0x8872,
+ 'FRAGMENT_PROGRAM_BINDING_NV': 0x8873,
+ 'PROGRAM_ERROR_STRING_NV': 0x8874,
+ 'MAX_PROGRAM_EXEC_INSTRUCTIONS_NV': 0x88F4,
+ 'MAX_PROGRAM_CALL_DEPTH_NV': 0x88F5,
+ 'MAX_PROGRAM_IF_DEPTH_NV': 0x88F6,
+ 'MAX_PROGRAM_LOOP_DEPTH_NV': 0x88F7,
+ 'MAX_PROGRAM_LOOP_COUNT_NV': 0x88F8,
+ 'RENDERBUFFER_COVERAGE_SAMPLES_NV': 0x8CAB,
+ 'RENDERBUFFER_COLOR_SAMPLES_NV': 0x8E10,
+ 'MAX_MULTISAMPLE_COVERAGE_MODES_NV': 0x8E11,
+ 'MULTISAMPLE_COVERAGE_MODES_NV': 0x8E12,
+ 'GEOMETRY_PROGRAM_NV': 0x8C26,
+ 'MAX_PROGRAM_OUTPUT_VERTICES_NV': 0x8C27,
+ 'MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV': 0x8C28,
+ 'MIN_PROGRAM_TEXEL_OFFSET_NV': 0x8904,
+ 'MAX_PROGRAM_TEXEL_OFFSET_NV': 0x8905,
+ 'PROGRAM_ATTRIB_COMPONENTS_NV': 0x8906,
+ 'PROGRAM_RESULT_COMPONENTS_NV': 0x8907,
+ 'MAX_PROGRAM_ATTRIB_COMPONENTS_NV': 0x8908,
+ 'MAX_PROGRAM_RESULT_COMPONENTS_NV': 0x8909,
+ 'MAX_PROGRAM_GENERIC_ATTRIBS_NV': 0x8DA5,
+ 'MAX_PROGRAM_GENERIC_RESULTS_NV': 0x8DA6,
+ 'HALF_FLOAT_NV': 0x140B,
+ 'MAX_SHININESS_NV': 0x8504,
+ 'MAX_SPOT_EXPONENT_NV': 0x8505,
+ 'MULTISAMPLE_FILTER_HINT_NV': 0x8534,
+ 'PIXEL_COUNTER_BITS_NV': 0x8864,
+ 'CURRENT_OCCLUSION_QUERY_ID_NV': 0x8865,
+ 'PIXEL_COUNT_NV': 0x8866,
+ 'PIXEL_COUNT_AVAILABLE_NV': 0x8867,
+ 'DEPTH_STENCIL_NV': 0x84F9,
+ 'UNSIGNED_INT_24_8_NV': 0x84FA,
+ 'MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV': 0x8DA0,
+ 'MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV': 0x8DA1,
+ 'VERTEX_PROGRAM_PARAMETER_BUFFER_NV': 0x8DA2,
+ 'GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV': 0x8DA3,
+ 'FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV': 0x8DA4,
+ 'WRITE_PIXEL_DATA_RANGE_NV': 0x8878,
+ 'READ_PIXEL_DATA_RANGE_NV': 0x8879,
+ 'WRITE_PIXEL_DATA_RANGE_LENGTH_NV': 0x887A,
+ 'READ_PIXEL_DATA_RANGE_LENGTH_NV': 0x887B,
+ 'WRITE_PIXEL_DATA_RANGE_POINTER_NV': 0x887C,
+ 'READ_PIXEL_DATA_RANGE_POINTER_NV': 0x887D,
+ 'POINT_SPRITE_NV': 0x8861,
+ 'COORD_REPLACE_NV': 0x8862,
+ 'POINT_SPRITE_R_MODE_NV': 0x8863,
+ 'FRAME_NV': 0x8E26,
+ 'FIELDS_NV': 0x8E27,
+ 'CURRENT_TIME_NV': 0x8E28,
+ 'NUM_FILL_STREAMS_NV': 0x8E29,
+ 'PRESENT_TIME_NV': 0x8E2A,
+ 'PRESENT_DURATION_NV': 0x8E2B,
+ 'PRIMITIVE_RESTART_NV': 0x8558,
+ 'PRIMITIVE_RESTART_INDEX_NV': 0x8559,
+ 'REGISTER_COMBINERS_NV': 0x8522,
+ 'VARIABLE_A_NV': 0x8523,
+ 'VARIABLE_B_NV': 0x8524,
+ 'VARIABLE_C_NV': 0x8525,
+ 'VARIABLE_D_NV': 0x8526,
+ 'VARIABLE_E_NV': 0x8527,
+ 'VARIABLE_F_NV': 0x8528,
+ 'VARIABLE_G_NV': 0x8529,
+ 'CONSTANT_COLOR0_NV': 0x852A,
+ 'CONSTANT_COLOR1_NV': 0x852B,
+ 'PRIMARY_COLOR_NV': 0x852C,
+ 'SECONDARY_COLOR_NV': 0x852D,
+ 'SPARE0_NV': 0x852E,
+ 'SPARE1_NV': 0x852F,
+ 'DISCARD_NV': 0x8530,
+ 'E_TIMES_F_NV': 0x8531,
+ 'SPARE0_PLUS_SECONDARY_COLOR_NV': 0x8532,
+ 'UNSIGNED_IDENTITY_NV': 0x8536,
+ 'UNSIGNED_INVERT_NV': 0x8537,
+ 'EXPAND_NORMAL_NV': 0x8538,
+ 'EXPAND_NEGATE_NV': 0x8539,
+ 'HALF_BIAS_NORMAL_NV': 0x853A,
+ 'HALF_BIAS_NEGATE_NV': 0x853B,
+ 'SIGNED_IDENTITY_NV': 0x853C,
+ 'SIGNED_NEGATE_NV': 0x853D,
+ 'SCALE_BY_TWO_NV': 0x853E,
+ 'SCALE_BY_FOUR_NV': 0x853F,
+ 'SCALE_BY_ONE_HALF_NV': 0x8540,
+ 'BIAS_BY_NEGATIVE_ONE_HALF_NV': 0x8541,
+ 'COMBINER_INPUT_NV': 0x8542,
+ 'COMBINER_MAPPING_NV': 0x8543,
+ 'COMBINER_COMPONENT_USAGE_NV': 0x8544,
+ 'COMBINER_AB_DOT_PRODUCT_NV': 0x8545,
+ 'COMBINER_CD_DOT_PRODUCT_NV': 0x8546,
+ 'COMBINER_MUX_SUM_NV': 0x8547,
+ 'COMBINER_SCALE_NV': 0x8548,
+ 'COMBINER_BIAS_NV': 0x8549,
+ 'COMBINER_AB_OUTPUT_NV': 0x854A,
+ 'COMBINER_CD_OUTPUT_NV': 0x854B,
+ 'COMBINER_SUM_OUTPUT_NV': 0x854C,
+ 'MAX_GENERAL_COMBINERS_NV': 0x854D,
+ 'NUM_GENERAL_COMBINERS_NV': 0x854E,
+ 'COLOR_SUM_CLAMP_NV': 0x854F,
+ 'COMBINER0_NV': 0x8550,
+ 'COMBINER1_NV': 0x8551,
+ 'COMBINER2_NV': 0x8552,
+ 'COMBINER3_NV': 0x8553,
+ 'COMBINER4_NV': 0x8554,
+ 'COMBINER5_NV': 0x8555,
+ 'COMBINER6_NV': 0x8556,
+ 'COMBINER7_NV': 0x8557,
+ 'PER_STAGE_CONSTANTS_NV': 0x8535,
+ 'EMBOSS_LIGHT_NV': 0x855D,
+ 'EMBOSS_CONSTANT_NV': 0x855E,
+ 'EMBOSS_MAP_NV': 0x855F,
+ 'NORMAL_MAP_NV': 0x8511,
+ 'REFLECTION_MAP_NV': 0x8512,
+ 'COMBINE4_NV': 0x8503,
+ 'SOURCE3_RGB_NV': 0x8583,
+ 'SOURCE3_ALPHA_NV': 0x858B,
+ 'OPERAND3_RGB_NV': 0x8593,
+ 'OPERAND3_ALPHA_NV': 0x859B,
+ 'TEXTURE_UNSIGNED_REMAP_MODE_NV': 0x888F,
+ 'TEXTURE_RECTANGLE_NV': 0x84F5,
+ 'TEXTURE_BINDING_RECTANGLE_NV': 0x84F6,
+ 'PROXY_TEXTURE_RECTANGLE_NV': 0x84F7,
+ 'MAX_RECTANGLE_TEXTURE_SIZE_NV': 0x84F8,
+ 'OFFSET_TEXTURE_RECTANGLE_NV': 0x864C,
+ 'OFFSET_TEXTURE_RECTANGLE_SCALE_NV': 0x864D,
+ 'DOT_PRODUCT_TEXTURE_RECTANGLE_NV': 0x864E,
+ 'RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV': 0x86D9,
+ 'UNSIGNED_INT_S8_S8_8_8_NV': 0x86DA,
+ 'UNSIGNED_INT_8_8_S8_S8_REV_NV': 0x86DB,
+ 'DSDT_MAG_INTENSITY_NV': 0x86DC,
+ 'SHADER_CONSISTENT_NV': 0x86DD,
+ 'TEXTURE_SHADER_NV': 0x86DE,
+ 'SHADER_OPERATION_NV': 0x86DF,
+ 'CULL_MODES_NV': 0x86E0,
+ 'OFFSET_TEXTURE_2D_MATRIX_NV': 0x86E1,
+ 'OFFSET_TEXTURE_MATRIX_NV': 0x86E1,
+ 'OFFSET_TEXTURE_2D_SCALE_NV': 0x86E2,
+ 'OFFSET_TEXTURE_SCALE_NV': 0x86E2,
+ 'OFFSET_TEXTURE_BIAS_NV': 0x86E3,
+ 'OFFSET_TEXTURE_2D_BIAS_NV': 0x86E3,
+ 'PREVIOUS_TEXTURE_INPUT_NV': 0x86E4,
+ 'CONST_EYE_NV': 0x86E5,
+ 'PASS_THROUGH_NV': 0x86E6,
+ 'CULL_FRAGMENT_NV': 0x86E7,
+ 'OFFSET_TEXTURE_2D_NV': 0x86E8,
+ 'DEPENDENT_AR_TEXTURE_2D_NV': 0x86E9,
+ 'DEPENDENT_GB_TEXTURE_2D_NV': 0x86EA,
+ 'DOT_PRODUCT_NV': 0x86EC,
+ 'DOT_PRODUCT_DEPTH_REPLACE_NV': 0x86ED,
+ 'DOT_PRODUCT_TEXTURE_2D_NV': 0x86EE,
+ 'DOT_PRODUCT_TEXTURE_CUBE_MAP_NV': 0x86F0,
+ 'DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV': 0x86F1,
+ 'DOT_PRODUCT_REFLECT_CUBE_MAP_NV': 0x86F2,
+ 'DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV': 0x86F3,
+ 'HILO_NV': 0x86F4,
+ 'DSDT_NV': 0x86F5,
+ 'DSDT_MAG_NV': 0x86F6,
+ 'DSDT_MAG_VIB_NV': 0x86F7,
+ 'HILO16_NV': 0x86F8,
+ 'SIGNED_HILO_NV': 0x86F9,
+ 'SIGNED_HILO16_NV': 0x86FA,
+ 'SIGNED_RGBA_NV': 0x86FB,
+ 'SIGNED_RGBA8_NV': 0x86FC,
+ 'SIGNED_RGB_NV': 0x86FE,
+ 'SIGNED_RGB8_NV': 0x86FF,
+ 'SIGNED_LUMINANCE_NV': 0x8701,
+ 'SIGNED_LUMINANCE8_NV': 0x8702,
+ 'SIGNED_LUMINANCE_ALPHA_NV': 0x8703,
+ 'SIGNED_LUMINANCE8_ALPHA8_NV': 0x8704,
+ 'SIGNED_ALPHA_NV': 0x8705,
+ 'SIGNED_ALPHA8_NV': 0x8706,
+ 'SIGNED_INTENSITY_NV': 0x8707,
+ 'SIGNED_INTENSITY8_NV': 0x8708,
+ 'DSDT8_NV': 0x8709,
+ 'DSDT8_MAG8_NV': 0x870A,
+ 'DSDT8_MAG8_INTENSITY8_NV': 0x870B,
+ 'SIGNED_RGB_UNSIGNED_ALPHA_NV': 0x870C,
+ 'SIGNED_RGB8_UNSIGNED_ALPHA8_NV': 0x870D,
+ 'HI_SCALE_NV': 0x870E,
+ 'LO_SCALE_NV': 0x870F,
+ 'DS_SCALE_NV': 0x8710,
+ 'DT_SCALE_NV': 0x8711,
+ 'MAGNITUDE_SCALE_NV': 0x8712,
+ 'VIBRANCE_SCALE_NV': 0x8713,
+ 'HI_BIAS_NV': 0x8714,
+ 'LO_BIAS_NV': 0x8715,
+ 'DS_BIAS_NV': 0x8716,
+ 'DT_BIAS_NV': 0x8717,
+ 'MAGNITUDE_BIAS_NV': 0x8718,
+ 'VIBRANCE_BIAS_NV': 0x8719,
+ 'TEXTURE_BORDER_VALUES_NV': 0x871A,
+ 'TEXTURE_HI_SIZE_NV': 0x871B,
+ 'TEXTURE_LO_SIZE_NV': 0x871C,
+ 'TEXTURE_DS_SIZE_NV': 0x871D,
+ 'TEXTURE_DT_SIZE_NV': 0x871E,
+ 'TEXTURE_MAG_SIZE_NV': 0x871F,
+ 'UNSIGNED_INT_S8_S8_8_8_NV': 0x86DA,
+ 'UNSIGNED_INT_8_8_S8_S8_REV_NV': 0x86DB,
+ 'DSDT_MAG_INTENSITY_NV': 0x86DC,
+ 'DOT_PRODUCT_TEXTURE_3D_NV': 0x86EF,
+ 'HILO_NV': 0x86F4,
+ 'DSDT_NV': 0x86F5,
+ 'DSDT_MAG_NV': 0x86F6,
+ 'DSDT_MAG_VIB_NV': 0x86F7,
+ 'HILO16_NV': 0x86F8,
+ 'SIGNED_HILO_NV': 0x86F9,
+ 'SIGNED_HILO16_NV': 0x86FA,
+ 'SIGNED_RGBA_NV': 0x86FB,
+ 'SIGNED_RGBA8_NV': 0x86FC,
+ 'SIGNED_RGB_NV': 0x86FE,
+ 'SIGNED_RGB8_NV': 0x86FF,
+ 'SIGNED_LUMINANCE_NV': 0x8701,
+ 'SIGNED_LUMINANCE8_NV': 0x8702,
+ 'SIGNED_LUMINANCE_ALPHA_NV': 0x8703,
+ 'SIGNED_LUMINANCE8_ALPHA8_NV': 0x8704,
+ 'SIGNED_ALPHA_NV': 0x8705,
+ 'SIGNED_ALPHA8_NV': 0x8706,
+ 'SIGNED_INTENSITY_NV': 0x8707,
+ 'SIGNED_INTENSITY8_NV': 0x8708,
+ 'DSDT8_NV': 0x8709,
+ 'DSDT8_MAG8_NV': 0x870A,
+ 'DSDT8_MAG8_INTENSITY8_NV': 0x870B,
+ 'SIGNED_RGB_UNSIGNED_ALPHA_NV': 0x870C,
+ 'SIGNED_RGB8_UNSIGNED_ALPHA8_NV': 0x870D,
+ 'OFFSET_PROJECTIVE_TEXTURE_2D_NV': 0x8850,
+ 'OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV': 0x8851,
+ 'OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV': 0x8852,
+ 'OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV': 0x8853,
+ 'OFFSET_HILO_TEXTURE_2D_NV': 0x8854,
+ 'OFFSET_HILO_TEXTURE_RECTANGLE_NV': 0x8855,
+ 'OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV': 0x8856,
+ 'OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV': 0x8857,
+ 'DEPENDENT_HILO_TEXTURE_2D_NV': 0x8858,
+ 'DEPENDENT_RGB_TEXTURE_3D_NV': 0x8859,
+ 'DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV': 0x885A,
+ 'DOT_PRODUCT_PASS_THROUGH_NV': 0x885B,
+ 'DOT_PRODUCT_TEXTURE_1D_NV': 0x885C,
+ 'DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV': 0x885D,
+ 'HILO8_NV': 0x885E,
+ 'SIGNED_HILO8_NV': 0x885F,
+ 'FORCE_BLUE_TO_ONE_NV': 0x8860,
+ 'BACK_PRIMARY_COLOR_NV': 0x8C77,
+ 'BACK_SECONDARY_COLOR_NV': 0x8C78,
+ 'TEXTURE_COORD_NV': 0x8C79,
+ 'CLIP_DISTANCE_NV': 0x8C7A,
+ 'VERTEX_ID_NV': 0x8C7B,
+ 'PRIMITIVE_ID_NV': 0x8C7C,
+ 'GENERIC_ATTRIB_NV': 0x8C7D,
+ 'TRANSFORM_FEEDBACK_ATTRIBS_NV': 0x8C7E,
+ 'TRANSFORM_FEEDBACK_BUFFER_MODE_NV': 0x8C7F,
+ 'MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV': 0x8C80,
+ 'ACTIVE_VARYINGS_NV': 0x8C81,
+ 'ACTIVE_VARYING_MAX_LENGTH_NV': 0x8C82,
+ 'TRANSFORM_FEEDBACK_VARYINGS_NV': 0x8C83,
+ 'TRANSFORM_FEEDBACK_BUFFER_START_NV': 0x8C84,
+ 'TRANSFORM_FEEDBACK_BUFFER_SIZE_NV': 0x8C85,
+ 'TRANSFORM_FEEDBACK_RECORD_NV': 0x8C86,
+ 'PRIMITIVES_GENERATED_NV': 0x8C87,
+ 'TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV': 0x8C88,
+ 'RASTERIZER_DISCARD_NV': 0x8C89,
+ 'MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV': 0x8C8A,
+ 'MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV': 0x8C8B,
+ 'INTERLEAVED_ATTRIBS_NV': 0x8C8C,
+ 'SEPARATE_ATTRIBS_NV': 0x8C8D,
+ 'TRANSFORM_FEEDBACK_BUFFER_NV': 0x8C8E,
+ 'TRANSFORM_FEEDBACK_BUFFER_BINDING_NV': 0x8C8F,
+ 'VERTEX_ARRAY_RANGE_NV': 0x851D,
+ 'VERTEX_ARRAY_RANGE_LENGTH_NV': 0x851E,
+ 'VERTEX_ARRAY_RANGE_VALID_NV': 0x851F,
+ 'MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV': 0x8520,
+ 'VERTEX_ARRAY_RANGE_POINTER_NV': 0x8521,
+ 'VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV': 0x8533,
+ 'VERTEX_PROGRAM_NV': 0x8620,
+ 'VERTEX_STATE_PROGRAM_NV': 0x8621,
+ 'ATTRIB_ARRAY_SIZE_NV': 0x8623,
+ 'ATTRIB_ARRAY_STRIDE_NV': 0x8624,
+ 'ATTRIB_ARRAY_TYPE_NV': 0x8625,
+ 'CURRENT_ATTRIB_NV': 0x8626,
+ 'PROGRAM_LENGTH_NV': 0x8627,
+ 'PROGRAM_STRING_NV': 0x8628,
+ 'MODELVIEW_PROJECTION_NV': 0x8629,
+ 'IDENTITY_NV': 0x862A,
+ 'INVERSE_NV': 0x862B,
+ 'TRANSPOSE_NV': 0x862C,
+ 'INVERSE_TRANSPOSE_NV': 0x862D,
+ 'MAX_TRACK_MATRIX_STACK_DEPTH_NV': 0x862E,
+ 'MAX_TRACK_MATRICES_NV': 0x862F,
+ 'MATRIX0_NV': 0x8630,
+ 'MATRIX1_NV': 0x8631,
+ 'MATRIX2_NV': 0x8632,
+ 'MATRIX3_NV': 0x8633,
+ 'MATRIX4_NV': 0x8634,
+ 'MATRIX5_NV': 0x8635,
+ 'MATRIX6_NV': 0x8636,
+ 'MATRIX7_NV': 0x8637,
+ 'CURRENT_MATRIX_STACK_DEPTH_NV': 0x8640,
+ 'CURRENT_MATRIX_NV': 0x8641,
+ 'VERTEX_PROGRAM_POINT_SIZE_NV': 0x8642,
+ 'VERTEX_PROGRAM_TWO_SIDE_NV': 0x8643,
+ 'PROGRAM_PARAMETER_NV': 0x8644,
+ 'ATTRIB_ARRAY_POINTER_NV': 0x8645,
+ 'PROGRAM_TARGET_NV': 0x8646,
+ 'PROGRAM_RESIDENT_NV': 0x8647,
+ 'TRACK_MATRIX_NV': 0x8648,
+ 'TRACK_MATRIX_TRANSFORM_NV': 0x8649,
+ 'VERTEX_PROGRAM_BINDING_NV': 0x864A,
+ 'PROGRAM_ERROR_POSITION_NV': 0x864B,
+ 'VERTEX_ATTRIB_ARRAY0_NV': 0x8650,
+ 'VERTEX_ATTRIB_ARRAY1_NV': 0x8651,
+ 'VERTEX_ATTRIB_ARRAY2_NV': 0x8652,
+ 'VERTEX_ATTRIB_ARRAY3_NV': 0x8653,
+ 'VERTEX_ATTRIB_ARRAY4_NV': 0x8654,
+ 'VERTEX_ATTRIB_ARRAY5_NV': 0x8655,
+ 'VERTEX_ATTRIB_ARRAY6_NV': 0x8656,
+ 'VERTEX_ATTRIB_ARRAY7_NV': 0x8657,
+ 'VERTEX_ATTRIB_ARRAY8_NV': 0x8658,
+ 'VERTEX_ATTRIB_ARRAY9_NV': 0x8659,
+ 'VERTEX_ATTRIB_ARRAY10_NV': 0x865A,
+ 'VERTEX_ATTRIB_ARRAY11_NV': 0x865B,
+ 'VERTEX_ATTRIB_ARRAY12_NV': 0x865C,
+ 'VERTEX_ATTRIB_ARRAY13_NV': 0x865D,
+ 'VERTEX_ATTRIB_ARRAY14_NV': 0x865E,
+ 'VERTEX_ATTRIB_ARRAY15_NV': 0x865F,
+ 'MAP1_VERTEX_ATTRIB0_4_NV': 0x8660,
+ 'MAP1_VERTEX_ATTRIB1_4_NV': 0x8661,
+ 'MAP1_VERTEX_ATTRIB2_4_NV': 0x8662,
+ 'MAP1_VERTEX_ATTRIB3_4_NV': 0x8663,
+ 'MAP1_VERTEX_ATTRIB4_4_NV': 0x8664,
+ 'MAP1_VERTEX_ATTRIB5_4_NV': 0x8665,
+ 'MAP1_VERTEX_ATTRIB6_4_NV': 0x8666,
+ 'MAP1_VERTEX_ATTRIB7_4_NV': 0x8667,
+ 'MAP1_VERTEX_ATTRIB8_4_NV': 0x8668,
+ 'MAP1_VERTEX_ATTRIB9_4_NV': 0x8669,
+ 'MAP1_VERTEX_ATTRIB10_4_NV': 0x866A,
+ 'MAP1_VERTEX_ATTRIB11_4_NV': 0x866B,
+ 'MAP1_VERTEX_ATTRIB12_4_NV': 0x866C,
+ 'MAP1_VERTEX_ATTRIB13_4_NV': 0x866D,
+ 'MAP1_VERTEX_ATTRIB14_4_NV': 0x866E,
+ 'MAP1_VERTEX_ATTRIB15_4_NV': 0x866F,
+ 'MAP2_VERTEX_ATTRIB0_4_NV': 0x8670,
+ 'MAP2_VERTEX_ATTRIB1_4_NV': 0x8671,
+ 'MAP2_VERTEX_ATTRIB2_4_NV': 0x8672,
+ 'MAP2_VERTEX_ATTRIB3_4_NV': 0x8673,
+ 'MAP2_VERTEX_ATTRIB4_4_NV': 0x8674,
+ 'MAP2_VERTEX_ATTRIB5_4_NV': 0x8675,
+ 'MAP2_VERTEX_ATTRIB6_4_NV': 0x8676,
+ 'MAP2_VERTEX_ATTRIB7_4_NV': 0x8677,
+ 'MAP2_VERTEX_ATTRIB8_4_NV': 0x8678,
+ 'MAP2_VERTEX_ATTRIB9_4_NV': 0x8679,
+ 'MAP2_VERTEX_ATTRIB10_4_NV': 0x867A,
+ 'MAP2_VERTEX_ATTRIB11_4_NV': 0x867B,
+ 'MAP2_VERTEX_ATTRIB12_4_NV': 0x867C,
+ 'MAP2_VERTEX_ATTRIB13_4_NV': 0x867D,
+ 'MAP2_VERTEX_ATTRIB14_4_NV': 0x867E,
+ 'MAP2_VERTEX_ATTRIB15_4_NV': 0x867F,
+ 'MAX_PROGRAM_EXEC_INSTRUCTIONS_NV': 0x88F4,
+ 'MAX_PROGRAM_CALL_DEPTH_NV': 0x88F5,
+ 'MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB': 0x8B4C,
+ 'BYTE': 0x1400,
+ 'PALETTE4_RGB8_OES': 0x8B90,
+ 'PALETTE4_RGBA8_OES': 0x8B91,
+ 'PALETTE4_R5_G6_B5_OES': 0x8B92,
+ 'PALETTE4_RGBA4_OES': 0x8B93,
+ 'PALETTE4_RGB5_A1_OES': 0x8B94,
+ 'PALETTE8_RGB8_OES': 0x8B95,
+ 'PALETTE8_RGBA8_OES': 0x8B96,
+ 'PALETTE8_R5_G6_B5_OES': 0x8B97,
+ 'PALETTE8_RGBA4_OES': 0x8B98,
+ 'PALETTE8_RGB5_A1_OES': 0x8B99,
+ 'IMPLEMENTATION_COLOR_READ_TYPE_OES': 0x8B9A,
+ 'IMPLEMENTATION_COLOR_READ_FORMAT_OES': 0x8B9B,
+ 'INTERLACE_OML': 0x8980,
+ 'INTERLACE_READ_OML': 0x8981,
+ 'PACK_RESAMPLE_OML': 0x8984,
+ 'UNPACK_RESAMPLE_OML': 0x8985,
+ 'RESAMPLE_REPLICATE_OML': 0x8986,
+ 'RESAMPLE_ZERO_FILL_OML': 0x8987,
+ 'RESAMPLE_AVERAGE_OML': 0x8988,
+ 'RESAMPLE_DECIMATE_OML': 0x8989,
+ 'FORMAT_SUBSAMPLE_24_24_OML': 0x8982,
+ 'FORMAT_SUBSAMPLE_244_244_OML': 0x8983,
+ 'VERTEX23_BIT_PGI': 0x00000004,
+ 'VERTEX4_BIT_PGI': 0x00000008,
+ 'COLOR3_BIT_PGI': 0x00010000,
+ 'COLOR4_BIT_PGI': 0x00020000,
+ 'EDGEFLAG_BIT_PGI': 0x00040000,
+ 'INDEX_BIT_PGI': 0x00080000,
+ 'MAT_AMBIENT_BIT_PGI': 0x00100000,
+ 'MAT_AMBIENT_AND_DIFFUSE_BIT_PGI': 0x00200000,
+ 'MAT_DIFFUSE_BIT_PGI': 0x00400000,
+ 'MAT_EMISSION_BIT_PGI': 0x00800000,
+ 'MAT_COLOR_INDEXES_BIT_PGI': 0x01000000,
+ 'MAT_SHININESS_BIT_PGI': 0x02000000,
+ 'MAT_SPECULAR_BIT_PGI': 0x04000000,
+ 'NORMAL_BIT_PGI': 0x08000000,
+ 'TEXCOORD1_BIT_PGI': 0x10000000,
+ 'TEXCOORD2_BIT_PGI': 0x20000000,
+ 'TEXCOORD3_BIT_PGI': 0x40000000,
+ 'TEXCOORD4_BIT_PGI': 0x80000000,
+ 'SCREEN_COORDINATES_REND': 0x8490,
+ 'INVERTED_SCREEN_W_REND': 0x8491,
+ 'RGB_S3TC': 0x83A0,
+ 'RGB4_S3TC': 0x83A1,
+ 'RGBA_S3TC': 0x83A2,
+ 'RGBA4_S3TC': 0x83A3,
+ 'RGBA_DXT5_S3TC': 0x83A4,
+ 'RGBA4_DXT5_S3TC': 0x83A5,
+ 'EXTENDED_RANGE_SGIS': 0x85A5,
+ 'MIN_RED_SGIS': 0x85A6,
+ 'MAX_RED_SGIS': 0x85A7,
+ 'MIN_GREEN_SGIS': 0x85A8,
+ 'MAX_GREEN_SGIS': 0x85A9,
+ 'MIN_BLUE_SGIS': 0x85AA,
+ 'MAX_BLUE_SGIS': 0x85AB,
+ 'MIN_ALPHA_SGIS': 0x85AC,
+ 'MAX_ALPHA_SGIS': 0x85AD,
+ 'GENERATE_MIPMAP_SGIS': 0x8191,
+ 'GENERATE_MIPMAP_HINT_SGIS': 0x8192,
+ 'MULTISAMPLE_SGIS': 0x809D,
+ 'SAMPLE_ALPHA_TO_MASK_SGIS': 0x809E,
+ 'SAMPLE_ALPHA_TO_ONE_SGIS': 0x809F,
+ 'SAMPLE_MASK_SGIS': 0x80A0,
+ '1PASS_SGIS': 0x80A1,
+ '2PASS_0_SGIS': 0x80A2,
+ '2PASS_1_SGIS': 0x80A3,
+ '4PASS_0_SGIS': 0x80A4,
+ '4PASS_1_SGIS': 0x80A5,
+ '4PASS_2_SGIS': 0x80A6,
+ '4PASS_3_SGIS': 0x80A7,
+ 'SAMPLE_BUFFERS_SGIS': 0x80A8,
+ 'SAMPLES_SGIS': 0x80A9,
+ 'SAMPLE_MASK_VALUE_SGIS': 0x80AA,
+ 'SAMPLE_MASK_INVERT_SGIS': 0x80AB,
+ 'SAMPLE_PATTERN_SGIS': 0x80AC,
+ 'MULTISAMPLE_BIT_EXT': 0x20000000,
+ 'EYE_DISTANCE_TO_POINT_SGIS': 0x81F0,
+ 'OBJECT_DISTANCE_TO_POINT_SGIS': 0x81F1,
+ 'EYE_DISTANCE_TO_LINE_SGIS': 0x81F2,
+ 'OBJECT_DISTANCE_TO_LINE_SGIS': 0x81F3,
+ 'EYE_POINT_SGIS': 0x81F4,
+ 'OBJECT_POINT_SGIS': 0x81F5,
+ 'EYE_LINE_SGIS': 0x81F6,
+ 'OBJECT_LINE_SGIS': 0x81F7,
+ 'CLAMP_TO_BORDER_SGIS': 0x812D,
+ 'CLAMP_TO_EDGE_SGIS': 0x812F,
+ 'TEXTURE_MIN_LOD_SGIS': 0x813A,
+ 'TEXTURE_MAX_LOD_SGIS': 0x813B,
+ 'TEXTURE_BASE_LEVEL_SGIS': 0x813C,
+ 'TEXTURE_MAX_LEVEL_SGIS': 0x813D,
+ 'ASYNC_MARKER_SGIX': 0x8329,
+ 'ASYNC_HISTOGRAM_SGIX': 0x832C,
+ 'MAX_ASYNC_HISTOGRAM_SGIX': 0x832D,
+ 'ASYNC_TEX_IMAGE_SGIX': 0x835C,
+ 'ASYNC_DRAW_PIXELS_SGIX': 0x835D,
+ 'ASYNC_READ_PIXELS_SGIX': 0x835E,
+ 'MAX_ASYNC_TEX_IMAGE_SGIX': 0x835F,
+ 'MAX_ASYNC_DRAW_PIXELS_SGIX': 0x8360,
+ 'MAX_ASYNC_READ_PIXELS_SGIX': 0x8361,
+ 'ALPHA_MIN_SGIX': 0x8320,
+ 'ALPHA_MAX_SGIX': 0x8321,
+ 'CONVOLUTION_HINT_SGIX': 0x8316,
+ 'DEPTH_COMPONENT16_SGIX': 0x81A5,
+ 'DEPTH_COMPONENT24_SGIX': 0x81A6,
+ 'DEPTH_COMPONENT32_SGIX': 0x81A7,
+ 'FOG_OFFSET_SGIX': 0x8198,
+ 'FOG_OFFSET_VALUE_SGIX': 0x8199,
+ 'INTERLACE_SGIX': 0x8094,
+ 'PACK_RESAMPLE_SGIX': 0x842E,
+ 'UNPACK_RESAMPLE_SGIX': 0x842F,
+ 'RESAMPLE_DECIMATE_SGIX': 0x8430,
+ 'RESAMPLE_REPLICATE_SGIX': 0x8433,
+ 'RESAMPLE_ZERO_FILL_SGIX': 0x8434,
+ 'TEXTURE_COMPARE_SGIX': 0x819A,
+ 'TEXTURE_COMPARE_OPERATOR_SGIX': 0x819B,
+ 'TEXTURE_LEQUAL_R_SGIX': 0x819C,
+ 'TEXTURE_GEQUAL_R_SGIX': 0x819D,
+ 'SHADOW_AMBIENT_SGIX': 0x80BF,
+ 'TEXTURE_MAX_CLAMP_S_SGIX': 0x8369,
+ 'TEXTURE_MAX_CLAMP_T_SGIX': 0x836A,
+ 'TEXTURE_MAX_CLAMP_R_SGIX': 0x836B,
+ 'TEXTURE_MULTI_BUFFER_HINT_SGIX': 0x812E,
+ 'RGB_SIGNED_SGIX': 0x85E0,
+ 'RGBA_SIGNED_SGIX': 0x85E1,
+ 'ALPHA_SIGNED_SGIX': 0x85E2,
+ 'LUMINANCE_SIGNED_SGIX': 0x85E3,
+ 'INTENSITY_SIGNED_SGIX': 0x85E4,
+ 'LUMINANCE_ALPHA_SIGNED_SGIX': 0x85E5,
+ 'RGB16_SIGNED_SGIX': 0x85E6,
+ 'RGBA16_SIGNED_SGIX': 0x85E7,
+ 'ALPHA16_SIGNED_SGIX': 0x85E8,
+ 'LUMINANCE16_SIGNED_SGIX': 0x85E9,
+ 'INTENSITY16_SIGNED_SGIX': 0x85EA,
+ 'LUMINANCE16_ALPHA16_SIGNED_SGIX': 0x85EB,
+ 'RGB_EXTENDED_RANGE_SGIX': 0x85EC,
+ 'RGBA_EXTENDED_RANGE_SGIX': 0x85ED,
+ 'ALPHA_EXTENDED_RANGE_SGIX': 0x85EE,
+ 'LUMINANCE_EXTENDED_RANGE_SGIX': 0x85EF,
+ 'INTENSITY_EXTENDED_RANGE_SGIX': 0x85F0,
+ 'LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX': 0x85F1,
+ 'RGB16_EXTENDED_RANGE_SGIX': 0x85F2,
+ 'RGBA16_EXTENDED_RANGE_SGIX': 0x85F3,
+ 'ALPHA16_EXTENDED_RANGE_SGIX': 0x85F4,
+ 'LUMINANCE16_EXTENDED_RANGE_SGIX': 0x85F5,
+ 'INTENSITY16_EXTENDED_RANGE_SGIX': 0x85F6,
+ 'LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX': 0x85F7,
+ 'MIN_LUMINANCE_SGIS': 0x85F8,
+ 'MAX_LUMINANCE_SGIS': 0x85F9,
+ 'MIN_INTENSITY_SGIS': 0x85FA,
+ 'MAX_INTENSITY_SGIS': 0x85FB,
+ 'POST_TEXTURE_FILTER_BIAS_SGIX': 0x8179,
+ 'POST_TEXTURE_FILTER_SCALE_SGIX': 0x817A,
+ 'POST_TEXTURE_FILTER_BIAS_RANGE_SGIX': 0x817B,
+ 'POST_TEXTURE_FILTER_SCALE_RANGE_SGIX': 0x817C,
+ 'VERTEX_PRECLIP_SGIX': 0x83EE,
+ 'VERTEX_PRECLIP_HINT_SGIX': 0x83EF,
+ 'VERTEX_PRECLIP_SGIX': 0x83EE,
+ 'VERTEX_PRECLIP_HINT_SGIX': 0x83EF,
+ 'COLOR_MATRIX_SGI': 0x80B1,
+ 'COLOR_MATRIX_STACK_DEPTH_SGI': 0x80B2,
+ 'MAX_COLOR_MATRIX_STACK_DEPTH_SGI': 0x80B3,
+ 'POST_COLOR_MATRIX_RED_SCALE_SGI': 0x80B4,
+ 'POST_COLOR_MATRIX_GREEN_SCALE_SGI': 0x80B5,
+ 'POST_COLOR_MATRIX_BLUE_SCALE_SGI': 0x80B6,
+ 'POST_COLOR_MATRIX_ALPHA_SCALE_SGI': 0x80B7,
+ 'POST_COLOR_MATRIX_RED_BIAS_SGI': 0x80B8,
+ 'POST_COLOR_MATRIX_GREEN_BIAS_SGI': 0x80B9,
+ 'POST_COLOR_MATRIX_BLUE_BIAS_SGI': 0x80BA,
+ 'POST_COLOR_MATRIX_ALPHA_BIAS_SGI': 0x80BB,
+ 'COLOR_TABLE_SGI': 0x80D0,
+ 'POST_CONVOLUTION_COLOR_TABLE_SGI': 0x80D1,
+ 'POST_COLOR_MATRIX_COLOR_TABLE_SGI': 0x80D2,
+ 'PROXY_COLOR_TABLE_SGI': 0x80D3,
+ 'PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI': 0x80D4,
+ 'PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI': 0x80D5,
+ 'COLOR_TABLE_SCALE_SGI': 0x80D6,
+ 'COLOR_TABLE_BIAS_SGI': 0x80D7,
+ 'COLOR_TABLE_FORMAT_SGI': 0x80D8,
+ 'COLOR_TABLE_WIDTH_SGI': 0x80D9,
+ 'COLOR_TABLE_RED_SIZE_SGI': 0x80DA,
+ 'COLOR_TABLE_GREEN_SIZE_SGI': 0x80DB,
+ 'COLOR_TABLE_BLUE_SIZE_SGI': 0x80DC,
+ 'COLOR_TABLE_ALPHA_SIZE_SGI': 0x80DD,
+ 'COLOR_TABLE_LUMINANCE_SIZE_SGI': 0x80DE,
+ 'COLOR_TABLE_INTENSITY_SIZE_SGI': 0x80DF,
+ 'TEXTURE_COLOR_TABLE_SGI': 0x80BC,
+ 'PROXY_TEXTURE_COLOR_TABLE_SGI': 0x80BD,
+ 'UNPACK_CONSTANT_DATA_SUNX': 0x81D5,
+ 'TEXTURE_CONSTANT_DATA_SUNX': 0x81D6,
+ 'WRAP_BORDER_SUN': 0x81D4,
+ 'GLOBAL_ALPHA_SUN': 0x81D9,
+ 'GLOBAL_ALPHA_FACTOR_SUN': 0x81DA,
+ 'QUAD_MESH_SUN': 0x8614,
+ 'TRIANGLE_MESH_SUN': 0x8615,
+ 'SLICE_ACCUM_SUN': 0x85CC,
+ 'RESTART_SUN': 0x01,
+ 'REPLACE_MIDDLE_SUN': 0x02,
+ 'REPLACE_OLDEST_SUN': 0x03,
+ 'TRIANGLE_LIST_SUN': 0x81D7,
+ 'REPLACEMENT_CODE_SUN': 0x81D8,
+ 'REPLACEMENT_CODE_ARRAY_SUN': 0x85C0,
+ 'REPLACEMENT_CODE_ARRAY_TYPE_SUN': 0x85C1,
+ 'REPLACEMENT_CODE_ARRAY_STRIDE_SUN': 0x85C2,
+ 'REPLACEMENT_CODE_ARRAY_POINTER_SUN': 0x85C3,
+ 'R1UI_V3F_SUN': 0x85C4,
+ 'R1UI_C4UB_V3F_SUN': 0x85C5,
+ 'R1UI_C3F_V3F_SUN': 0x85C6,
+ 'R1UI_N3F_V3F_SUN': 0x85C7,
+ 'R1UI_C4F_N3F_V3F_SUN': 0x85C8,
+ 'R1UI_T2F_V3F_SUN': 0x85C9,
+ 'R1UI_T2F_N3F_V3F_SUN': 0x85CA,
+ 'R1UI_T2F_C4F_N3F_V3F_SUN': 0x85CB,
+ 'PHONG_WIN': 0x80EA,
+ 'PHONG_HINT_WIN': 0x80EB,
+ 'PROGRAM_BINARY_RETRIEVABLE_HINT': 0x8257,
+ 'PROGRAM_BINARY_LENGTH': 0x8741,
+ 'PROGRAM_BINARY_FORMATS': 0x87FE,
+ 'NUM_PROGRAM_BINARY_FORMATS': 0x87FF,
+ 'PRIMITIVE_RESTART_FIXED_INDEX': 0x8D69,
+ 'FOG_SPECULAR_TEXTURE_WIN': 0x80EC
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js b/dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js
new file mode 100644
index 000000000..a4c93d7ae
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js
@@ -0,0 +1,393 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+GLSLConformanceTester = (function(){
+
+var wtu = WebGLTestUtils;
+var defaultVertexShader = [
+ "attribute vec4 vPosition;",
+ "void main()",
+ "{",
+ " gl_Position = vPosition;",
+ "}"
+].join('\n');
+
+var defaultFragmentShader = [
+ "precision mediump float;",
+ "void main()",
+ "{",
+ " gl_FragColor = vec4(1.0,0.0,0.0,1.0);",
+ "}"
+].join('\n');
+
+var defaultESSL3VertexShader = [
+ "#version 300 es",
+ "in vec4 vPosition;",
+ "void main()",
+ "{",
+ " gl_Position = vPosition;",
+ "}"
+].join('\n');
+
+var defaultESSL3FragmentShader = [
+ "#version 300 es",
+ "precision mediump float;",
+ "out vec4 my_FragColor;",
+ "void main()",
+ "{",
+ " my_FragColor = vec4(1.0,0.0,0.0,1.0);",
+ "}"
+].join('\n');
+
+function log(msg) {
+ bufferedLogToConsole(msg);
+}
+
+var vShaderDB = {};
+var fShaderDB = {};
+
+/**
+ * The info parameter should contain the following keys. Note that you may leave
+ * the parameters for one shader out, in which case the default shader will be
+ * used.
+ * vShaderSource: the source code for vertex shader
+ * vShaderId: id of an element containing vertex shader source code. Used if
+ * vShaderSource is not specified.
+ * vShaderSuccess: true if vertex shader compilation should
+ * succeed.
+ * fShaderSource: the source code for fragment shader
+ * fShaderId: id of an element containing fragment shader source code. Used if
+ * fShaderSource is not specified.
+ * fShaderSuccess: true if fragment shader compilation should
+ * succeed.
+ * linkSuccess: true if link should succeed
+ * passMsg: msg to describe success condition.
+ * render: if true render to unit quad. Green = success
+ * uniforms: an array of objects specifying uniforms to set prior to rendering.
+ * Each object should have the following keys:
+ * name: uniform variable name in the shader source. Uniform location will
+ * be queried based on its name.
+ * functionName: name of the function used to set the uniform. For example:
+ * 'uniform1i'
+ * value: value of the uniform to set.
+ */
+function runOneTest(gl, info) {
+ var passMsg = info.passMsg
+ debug("");
+ debug("test: " + passMsg);
+
+ var consoleDiv = document.getElementById("console");
+
+ var vIsDefault = false;
+ var fIsDefault = false;
+
+ if (info.vShaderSource === undefined) {
+ if (info.vShaderId) {
+ info.vShaderSource = document.getElementById(info.vShaderId).text;
+ } else {
+ vIsDefault = true;
+ }
+ }
+ if (info.fShaderSource === undefined) {
+ if (info.fShaderId) {
+ info.fShaderSource = document.getElementById(info.fShaderId).text;
+ } else {
+ fIsDefault = true;
+ }
+ }
+
+ var vLabel = (vIsDefault ? "default" : "test") + " vertex shader";
+ var fLabel = (fIsDefault ? "default" : "test") + " fragment shader";
+ if (vIsDefault) {
+ info.vShaderSource = defaultVertexShader;
+ info.vShaderSuccess = true;
+ }
+ if (fIsDefault) {
+ info.fShaderSource = defaultFragmentShader;
+ info.fShaderSuccess = true;
+ }
+
+ if (vIsDefault != fIsDefault) {
+ // The language version of the default shader is chosen
+ // according to the language version of the other shader.
+ // We rely on "#version 300 es" being in this usual format.
+ // It must be on the first line of the shader according to the spec.
+ if (fIsDefault) {
+ // If we're using the default fragment shader, we need to make sure that
+ // it's language version matches with the vertex shader.
+ if (info.vShaderSource.split('\n')[0] == '#version 300 es') {
+ info.fShaderSource = defaultESSL3FragmentShader;
+ }
+ } else {
+ // If we're using the default vertex shader, we need to make sure that
+ // it's language version matches with the fragment shader.
+ if (info.fShaderSource.split('\n')[0] == '#version 300 es') {
+ info.vShaderSource = defaultESSL3VertexShader;
+ }
+ }
+ }
+
+ var vSource = info.vShaderPrep ? info.vShaderPrep(info.vShaderSource) :
+ info.vShaderSource;
+
+ if (!quietMode())
+ wtu.addShaderSource(consoleDiv, vLabel, vSource);
+
+ // Reuse identical shaders so we test shared shader.
+ var vShader = vShaderDB[vSource];
+ if (!vShader) {
+ vShader = wtu.loadShader(gl, vSource, gl.VERTEX_SHADER);
+ if (info.vShaderTest) {
+ if (!info.vShaderTest(vShader)) {
+ testFailed("[vertex shader test] " + passMsg);
+ return;
+ }
+ }
+ // As per GLSL 1.0.17 10.27 we can only check for success on
+ // compileShader, not failure.
+ if (!info.ignoreResults && info.vShaderSuccess && !vShader) {
+ testFailed("[unexpected vertex shader compile status] (expected: " +
+ info.vShaderSuccess + ") " + passMsg);
+ }
+ // Save the shaders so we test shared shader.
+ if (vShader) {
+ vShaderDB[vSource] = vShader;
+ }
+ }
+
+ var debugShaders = gl.getExtension('WEBGL_debug_shaders');
+ if (debugShaders && vShader && !quietMode()) {
+ wtu.addShaderSource(consoleDiv, vLabel + " translated for driver",
+ debugShaders.getTranslatedShaderSource(vShader));
+ }
+
+ var fSource = info.fShaderPrep ? info.fShaderPrep(info.fShaderSource) :
+ info.fShaderSource;
+
+ if (!quietMode())
+ wtu.addShaderSource(consoleDiv, fLabel, fSource);
+
+ // Reuse identical shaders so we test shared shader.
+ var fShader = fShaderDB[fSource];
+ if (!fShader) {
+ fShader = wtu.loadShader(gl, fSource, gl.FRAGMENT_SHADER);
+ if (info.fShaderTest) {
+ if (!info.fShaderTest(fShader)) {
+ testFailed("[fragment shader test] " + passMsg);
+ return;
+ }
+ }
+ //debug(fShader == null ? "fail" : "succeed");
+ // As per GLSL 1.0.17 10.27 we can only check for success on
+ // compileShader, not failure.
+ if (!info.ignoreResults && info.fShaderSuccess && !fShader) {
+ testFailed("[unexpected fragment shader compile status] (expected: " +
+ info.fShaderSuccess + ") " + passMsg);
+ return;
+ }
+
+ // Safe the shaders so we test shared shader.
+ if (fShader) {
+ fShaderDB[fSource] = fShader;
+ }
+ }
+
+ if (debugShaders && fShader && !quietMode()) {
+ wtu.addShaderSource(consoleDiv, fLabel + " translated for driver",
+ debugShaders.getTranslatedShaderSource(fShader));
+ }
+
+ if (vShader && fShader) {
+ var program = gl.createProgram();
+ gl.attachShader(program, vShader);
+ gl.attachShader(program, fShader);
+
+ if (vSource.indexOf("vPosition") >= 0) {
+ gl.bindAttribLocation(program, 0, "vPosition");
+ }
+ if (vSource.indexOf("texCoord0") >= 0) {
+ gl.bindAttribLocation(program, 1, "texCoord0");
+ }
+ gl.linkProgram(program);
+ var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
+ if (!linked) {
+ var error = gl.getProgramInfoLog(program);
+ log("*** Error linking program '"+program+"':"+error);
+ }
+ if (!info.ignoreResults && linked != info.linkSuccess) {
+ testFailed("[unexpected link status] " + passMsg);
+ return;
+ }
+ } else {
+ if (!info.ignoreResults && info.linkSuccess) {
+ testFailed("[link failed] " + passMsg);
+ return;
+ }
+ }
+
+ if (parseInt(wtu.getUrlOptions().dumpShaders)) {
+ var vInfo = {
+ shader: vShader,
+ shaderSuccess: info.vShaderSuccess,
+ label: vLabel,
+ source: vSource
+ };
+ var fInfo = {
+ shader: fShader,
+ shaderSuccess: info.fShaderSuccess,
+ label: fLabel,
+ source: fSource
+ };
+ wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vInfo, fInfo);
+ }
+
+ if (!info.render) {
+ testPassed(passMsg);
+ return;
+ }
+
+ gl.useProgram(program);
+
+ if (info.uniforms !== undefined) {
+ for (var i = 0; i < info.uniforms.length; ++i) {
+ var uniformLocation = gl.getUniformLocation(program, info.uniforms[i].name);
+ gl[info.uniforms[i].functionName](uniformLocation, info.uniforms[i].value);
+ debug(info.uniforms[i].name + ' set to ' + info.uniforms[i].value);
+ }
+ }
+
+ wtu.setupUnitQuad(gl);
+ wtu.clearAndDrawUnitQuad(gl);
+
+ var div = document.createElement("div");
+ div.className = "testimages";
+ wtu.insertImage(div, "result", wtu.makeImageFromCanvas(gl.canvas));
+ div.appendChild(document.createElement('br'));
+ consoleDiv.appendChild(div);
+
+ var tolerance = 0;
+ if (info.renderTolerance !== undefined) {
+ tolerance = info.renderTolerance;
+ }
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", tolerance);
+}
+
+function runTests(shaderInfos, opt_contextVersion) {
+ var wtu = WebGLTestUtils;
+ var canvas = document.createElement('canvas');
+ canvas.width = 32;
+ canvas.height = 32;
+ var gl = wtu.create3DContext(canvas, undefined, opt_contextVersion);
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+
+ var testIndex = 0;
+ var runNextTest = function() {
+ if (testIndex == shaderInfos.length) {
+ finishTest();
+ return;
+ }
+
+ runOneTest(gl, shaderInfos[testIndex++]);
+ setTimeout(runNextTest, 1);
+ }
+ runNextTest();
+};
+
+function getSource(elem) {
+ var str = elem.text;
+ return str.replace(/^\s*/, '').replace(/\s*$/, '');
+}
+
+function getPassMessage(source) {
+ var lines = source.split('\n');
+ return lines[0].substring(3);
+}
+
+function getSuccess(msg) {
+ if (msg.indexOf("fail") >= 0) {
+ return false;
+ }
+ if (msg.indexOf("succeed") >= 0) {
+ return true;
+ }
+ testFailed("bad test description. Must have 'fail' or 'succeed'");
+}
+
+function setupTest() {
+ var info = {};
+
+ var vShaderElem = document.getElementById('vertexShader');
+ if (vShaderElem) {
+ info.vShaderSource = getSource(vShaderElem);
+ info.passMsg = getPassMessage(info.vShaderSource);
+ info.vShaderSuccess = getSuccess(info.passMsg);
+ }
+
+ var fShaderElem = document.getElementById('fragmentShader');
+ if (fShaderElem) {
+ info.fShaderSource = getSource(fShaderElem);
+ info.passMsg = getPassMessage(info.fShaderSource);
+ info.fShaderSuccess = getSuccess(info.passMsg);
+ }
+
+ // linkSuccess should be true if shader success value is undefined or true for both shaders.
+ info.linkSuccess = info.vShaderSuccess !== false && info.fShaderSuccess !== false;
+
+ if (info.passMsg === undefined) {
+ testFailed("no test shader found.");
+ finishTest();
+ return;
+ }
+
+ return info;
+}
+
+function runTest() {
+ var info = setupTest();
+ description(info.passMsg);
+ runTests([info]);
+}
+
+function runRenderTests(tests, opt_contextVersion) {
+ for (var ii = 0; ii < tests.length; ++ii) {
+ tests[ii].render = true
+ }
+ runTests(tests, opt_contextVersion);
+}
+
+function runRenderTest() {
+ var info = setupTest();
+ description(info.passMsg);
+ runRenderTests([info]);
+}
+
+return {
+ runTest: runTest,
+ runTests: runTests,
+ runRenderTest: runRenderTest,
+ runRenderTests: runRenderTests
+};
+}());
diff --git a/dom/canvas/test/webgl-conf/checkout/js/glsl-constructor-tests-generator.js b/dom/canvas/test/webgl-conf/checkout/js/glsl-constructor-tests-generator.js
new file mode 100644
index 000000000..7f796c2cd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/glsl-constructor-tests-generator.js
@@ -0,0 +1,936 @@
+/*
+** Copyright (c) 2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+
+var GLSLConstructorTestsGenerator = (function() {
+
+var wtu = WebGLTestUtils;
+
+// Shader code templates
+var constructorVertexTemplate = [
+ "attribute vec4 vPosition;",
+
+ "precision mediump int;",
+ "precision mediump float;",
+
+ // Colors used to signal correctness of component values comparison
+ "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);",
+ "const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);",
+
+ // Error bound used in comparison of floating point values
+ "$(errorBound)",
+
+ "varying vec4 vColor;",
+
+ "void main() {",
+ " $(argsList)",
+
+ " $(type) v = $(type)($(argsConstr));",
+
+ " if ($(checkCompVals))",
+ " vColor = green;",
+ " else",
+ " vColor = red;",
+
+ " gl_Position = vPosition;",
+ "}"
+].join("\n");
+
+
+var passThroughColorFragmentShader = [
+ "precision mediump float;",
+
+ "varying vec4 vColor;",
+
+ "void main() {",
+ " gl_FragColor = vColor;",
+ "}"
+].join('\n');
+
+
+var constructorFragmentTemplate = [
+ "precision mediump int;",
+ "precision mediump float;",
+
+ // Colors used to signal correctness of component values comparison
+ "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0); ",
+ "const vec4 red = vec4(1.0, 0.0, 0.0, 1.0); ",
+
+ // Error bound used in comparison of floating point values
+ "$(errorBound)",
+
+ "void main() {",
+ " $(argsList)",
+
+ " $(type) v = $(type)($(argsConstr));",
+
+ " if ($(checkCompVals))",
+ " gl_FragColor = green;",
+ " else",
+ " gl_FragColor = red;",
+ "}"
+].join("\n");
+
+
+// Coding of the different argument types
+// s : scalar
+// v2 : vec2
+// v3 : vec3
+// v4 : vec4
+// m2 : mat2
+// m3 : mat3
+// m4 : mat4
+
+// Returns the dimensions of the type
+// Count of columns, count of rows
+function getTypeCodeDimensions(typeCode) {
+ switch (typeCode) {
+ case "s": return [1, 1];
+ case "v2": return [1, 2];
+ case "v3": return [1, 3];
+ case "v4": return [1, 4];
+ case "m2": return [2, 2];
+ case "m3": return [3, 3];
+ case "m4": return [4, 4];
+
+ default:
+ wtu.error("GLSLConstructorTestsGenerator.getTypeCodeDimensions(), unknown type code");
+ debugger;
+ }
+};
+
+
+// Returns the component count for the type code
+function getTypeCodeComponentCount(typeCode) {
+ var dim = getTypeCodeDimensions(typeCode);
+
+ return dim[0] * dim[1];
+}
+
+
+// Returns glsl name of type code
+function getGLSLBaseTypeName(typeCode) {
+ switch(typeCode) {
+ case "s": return "";
+ case "v2": return "vec2";
+ case "v3": return "vec3";
+ case "v4": return "vec4";
+ case "m2": return "mat2";
+ case "m3": return "mat3";
+ case "m4": return "mat4";
+
+ default:
+ wtu.error("GLSLConstructorTestsGenerator.getGLSLBaseTypeName(), unknown type code");
+ debugger;
+ }
+}
+
+
+// Returns the scalar glsl type name related to the structured type
+function getGLSLScalarType(targetType) {
+ switch(targetType[0]) {
+ case 'i': return "int";
+ case 'b': return "bool";
+
+ case 'v':
+ case 'm':
+ return "float";
+
+ default:
+ wtu.error("GLSLConstructorTestsGenerator.getGLSLScalarType(), unknown target type");
+ debugger;
+ }
+}
+
+
+// Returns the scalar prefix for the associated scalar type
+function getGLSLScalarPrefix(targetType) {
+ switch(targetType[0]) {
+ case 'i':
+ case 'b':
+ return targetType[0];
+
+ case 'v':
+ case 'm':
+ return '';
+
+ default:
+ wtu.error("GLSLConstructorTestsGenerator.getGLSLScalarPrefix(), unknown target type");
+ debugger;
+ }
+}
+
+
+// Returns the type for a specified target type and argument type code
+function getGLSLArgumentType(typeCode, targetType) {
+ var baseType = getGLSLBaseTypeName(typeCode);
+ if (baseType !== "") {
+ if (typeCode[0] === "v") {
+ // Vectors come in different flavours
+ return getGLSLScalarPrefix(targetType) + baseType;
+ }
+ else
+ return baseType;
+ }
+ else
+ return getGLSLScalarType(targetType);
+}
+
+
+// Returns the glsl type of the argument components
+function getGLSLArgumentComponentType(argTypeCode, targetType) {
+ var scalarType;
+
+ if (argTypeCode[0] === "m") {
+ // Matrices are always floats
+ scalarType = "float";
+ }
+ else
+ scalarType = getGLSLScalarType(targetType);
+
+ return scalarType;
+}
+
+
+function getGLSLColumnSize(targetType) {
+ colSize = parseInt(targetType.slice(-1));
+
+ if (!isNaN(colSize))
+ return colSize;
+
+ wtu.error("GLSLConstructorTestsGenerator.getGLSLColumnSize(), invalid target type");
+ debugger;
+}
+
+
+// Returns correct string representation of scalar value
+function getScalarTypeValStr(val, scalarType) {
+ if (val == null)
+ debugger;
+
+ switch (scalarType) {
+ case "float": return val.toFixed(1);
+ case "int": return val;
+ case "bool": return (val === 0) ? "false" : "true";
+
+ default:
+ wtu.error("GLSLConstructorTestsGenerator.getScalarTypeValStr(), unknown scalar type");
+ debugger;
+ }
+}
+
+
+// Returns true if the glsl type name is a matrix
+function isGLSLTypeMatrix(type) {
+ return (type.indexOf("mat") !== -1);
+}
+
+
+// Returns true if the glsl type name is a vector
+function isGLSLTypeVector(type) {
+ return (type.indexOf("vec") !== -1);
+}
+
+
+// Returns the count of components
+function getGLSLTypeComponentCount(type) {
+ var colSize = getGLSLColumnSize(type);
+
+ if (isGLSLTypeMatrix(type))
+ return colSize * colSize;
+ else
+ return colSize;
+}
+
+
+// Returns the constructor expression with the components set to a sequence of scalar values
+// Like vec3(1.0, 2.0, 3.0)
+function getComponentSequenceConstructorExpression(typeCode, firstCompValue, targetType) {
+ var scalarType = getGLSLArgumentComponentType(typeCode, targetType);
+
+ if (typeCode === "s") {
+ // Scalar
+ return getScalarTypeValStr(firstCompValue, scalarType) + ";";
+ }
+ else {
+ // Structured typeargTypeCode[0] === "m"
+ compCount = getTypeCodeComponentCount(typeCode);
+ var constrExpParts = new Array(compCount);
+ for (var aa = 0; aa < compCount; ++aa)
+ constrExpParts[aa] = getScalarTypeValStr(firstCompValue + aa, scalarType);
+
+ return getGLSLArgumentType(typeCode, targetType) + "(" + constrExpParts.join(", ") + ");";
+ }
+}
+
+
+// Returns the expression to select a component of the structured type
+function getComponentSelectorExpStr(targetType, compIx) {
+ if (isGLSLTypeMatrix(targetType)) {
+ var colRowIx = getColRowIndexFromLinearIndex(compIx, getGLSLColumnSize(targetType));
+ return "v[" + colRowIx.colIx + "][" + colRowIx.rowIx + "]";
+ }
+ else
+ return "v[" + compIx + "]";
+}
+
+
+// Returns expression which validates the components set by the constructor expression
+function getComponentValidationExpression(refCompVals, targetType) {
+ // Early out for invalid arguments
+ if (refCompVals.length === 0)
+ return "false";
+
+ var scalarType = getGLSLScalarType(targetType);
+ var checkComponentValueParts = new Array(refCompVals.length);
+ for (var cc = 0; cc < refCompVals.length; ++cc) {
+ var val_str = getScalarTypeValStr(refCompVals[cc], scalarType);
+ var comp_sel_exp = getComponentSelectorExpStr(targetType, cc);
+ if (scalarType === "float") {
+ // Comparison of floating point values with error bound
+ checkComponentValueParts[cc] = "abs(" + comp_sel_exp + " - " + val_str + ") <= errorBound";
+ }
+ else {
+ // Simple comparison to expected value
+ checkComponentValueParts[cc] = comp_sel_exp + " == " + val_str;
+ }
+ }
+
+ return checkComponentValueParts.join(" && ");
+}
+
+
+// Returns substitution parts to turn the shader template into testable shader code
+function getTestShaderParts(targetType, argExp, firstCompValue) {
+ // glsl code of declarations of arguments
+ var argsListParts = new Array(argExp.length);
+
+ // glsl code of constructor expression
+ var argsConstrParts = new Array(argExp.length);
+
+ // glsl type expression
+ var typeExpParts = new Array(argExp.length);
+ for (var aa = 0; aa < argExp.length; ++aa) {
+ var typeCode = argExp[aa];
+ var argCompCount = getTypeCodeComponentCount(typeCode);
+ var argName = "a" + aa;
+ var argType = getGLSLArgumentType(typeCode, targetType);
+ var argConstrExp = argType + " " + argName + " = " + getComponentSequenceConstructorExpression(typeCode, firstCompValue, targetType);
+
+ // Add construction of one argument
+ // Indent if not first argument
+ argsListParts[aa] = ((aa > 0) ? " " : "") + argConstrExp;
+
+ // Add argument name to target type argument list
+ argsConstrParts[aa] = argName;
+
+ // Add type name to type expression
+ typeExpParts[aa] = argType;
+
+ // Increment argument component value so all argument component arguments have a unique value
+ firstCompValue += argCompCount;
+ }
+
+ return {
+ argsList: argsListParts.join("\n") + "\n",
+ argsConstr: argsConstrParts.join(", "),
+ typeExp: targetType + "(" + typeExpParts.join(", ") + ")"
+ };
+}
+
+
+// Utility functions to manipulate the array of reference values
+
+// Returns array filled with identical values
+function getArrayWithIdenticalValues(size, val) {
+ var matArray = new Array(size);
+ for (var aa = 0; aa < size; ++aa)
+ matArray[aa] = val;
+
+ return matArray;
+}
+
+
+// Returns array filled with increasing values from a specified start value
+function getArrayWithIncreasingValues(size, start) {
+ var matArray = new Array(size);
+ for (var aa = 0; aa < size; ++aa)
+ matArray[aa] = start + aa;
+
+ return matArray;
+}
+
+
+// Utility functions to manipulate the array of reference values if the target type is a matrix
+
+// Returns an array which is the column order layout of a square matrix where the diagonal is set to a specified value
+function matCompArraySetDiagonal(matArray, diagVal) {
+ // The entries for the diagonal start at array index 0 and increase
+ // by column size + 1
+ var colSize = Math.round(Math.sqrt(matArray.length));
+ var dIx = 0;
+ do {
+ matArray[dIx] = diagVal;
+ dIx += (colSize + 1);
+ }
+ while (dIx < colSize * colSize);
+
+ return matArray;
+}
+
+
+// Returns an array which contains the values of an identity matrix read out in column order
+function matCompArrayCreateDiagonalMatrix(colSize, diagVal) {
+ var size = colSize * colSize;
+ var matArray = new Array(size);
+ for (var aa = 0; aa < size; ++aa)
+ matArray[aa] = 0;
+
+ return matCompArraySetDiagonal(matArray, diagVal);
+}
+
+
+// Returns the column and row index from the linear index if the components of the matrix are stored in column order in an array
+// in a one dimensional array in column order
+function getColRowIndexFromLinearIndex(linIx, colSize) {
+ return {
+ colIx: Math.floor(linIx / colSize),
+ rowIx: linIx % colSize
+ };
+}
+
+
+// Returns the linear index for matrix column and row index for a specified matrix size
+function getLinearIndexFromColRowIndex(rowColIx, colSize) {
+ return rowColIx.colIx * colSize + rowColIx.rowIx;
+}
+
+
+// Returns a matrix set from another matrix
+function matCompArraySetMatrixFromMatrix(dstColSize, srcMatArray) {
+ // Overwrite components from destination with the source component values at the same col, row coordinates
+ var dstMatArray = matCompArrayCreateDiagonalMatrix(dstColSize, 1);
+
+ var srcColSize = Math.round(Math.sqrt(srcMatArray.length));
+
+ for (var c_ix = 0; c_ix < srcMatArray.length; ++c_ix) {
+ var srcMatIx = getColRowIndexFromLinearIndex(c_ix, srcColSize);
+ if (srcMatIx.colIx < dstColSize && srcMatIx.rowIx < dstColSize) {
+ // Source matrix coordinates are valid destination matrix coordinates
+ dstMatArray[getLinearIndexFromColRowIndex(srcMatIx, dstColSize)] = srcMatArray[c_ix];
+ }
+ }
+
+ return dstMatArray;
+}
+
+
+// Returns the glsl code to verify if the components are set correctly
+// and the message to display for the test
+function getConstructorExpressionInfo(targetType, argExp, firstCompValue) {
+ var argCompCountsSum = 0;
+ var argCompCounts = new Array(argExp.length);
+ for (var aa = 0; aa < argExp.length; ++aa) {
+ argCompCounts[aa] = getTypeCodeComponentCount(argExp[aa]);
+ argCompCountsSum += argCompCounts[aa];
+ }
+
+ var targetCompCount = getGLSLTypeComponentCount(targetType);
+
+ var refCompVals;
+ var testMsg;
+ var valid;
+
+ if (argCompCountsSum === 0) {
+ // A constructor needs at least one argument
+ refCompVals = [];
+ testMsg = "invalid (no arguments)";
+ valid = false;
+ }
+ else {
+ if (isGLSLTypeVector(targetType)) {
+ if (argCompCountsSum === 1) {
+ // One scalar argument
+ // Vector constructor with one scalar argument set all components to the same value
+ refCompVals = getArrayWithIdenticalValues(targetCompCount, firstCompValue);
+ testMsg = "valid (all components set to the same value)";
+ valid = true;
+ }
+ else {
+ // Not one scalar argument
+ if (argCompCountsSum < targetCompCount) {
+ // Not all components set
+ refCompVals = [];
+ testMsg = "invalid (not enough arguments)";
+ valid = false;
+ }
+ else {
+ // argCompCountsSum >= targetCompCount
+ // All components set
+ var lastArgFirstCompIx = argCompCountsSum - argCompCounts[argCompCounts.length - 1];
+
+ if (lastArgFirstCompIx < targetCompCount) {
+ // First component of last argument is used
+ refCompVals = getArrayWithIncreasingValues(targetCompCount, firstCompValue);
+ testMsg = "valid";
+ valid = true;
+ }
+ else {
+ // First component of last argument is not used
+ refCompVals = [];
+ testMsg = "invalid (unused argument)";
+ valid = false;
+ }
+ }
+ }
+ }
+ else {
+ // Matrix target type
+ if (argCompCountsSum === 1) {
+ // One scalar argument
+ // Matrix constructors with one scalar set all components on the diagonal to the same value
+ // All other components are set to zero
+ refCompVals = matCompArrayCreateDiagonalMatrix(Math.round(Math.sqrt(targetCompCount)), firstCompValue);
+ testMsg = "valid (diagonal components set to the same value, off-diagonal components set to zero)";
+ valid = true;
+ }
+ else {
+ // Not one scalar argument
+ if (argExp.length === 1 && argExp[0][0] === "m") {
+ // One single matrix argument
+ var dstColSize = getGLSLColumnSize(targetType);
+ refCompVals = matCompArraySetMatrixFromMatrix(dstColSize, getArrayWithIncreasingValues(getTypeCodeComponentCount(argExp[0]), firstCompValue));
+ testMsg = "valid, components at corresponding col, row indices are set from argument, other components are set from identity matrix";
+ valid = true;
+ }
+ else {
+ // More than one argument or one argument not of type matrix
+ // Can be treated in the same manner
+ // Arguments can not be of type matrix
+ var matFound = false;
+ for (var aa = 0; aa < argExp.length; ++aa)
+ if (argExp[aa][0] === "m")
+ matFound = true;
+
+ if (matFound) {
+ refCompVals = [];
+ testMsg = "invalid, argument list greater than one contains matrix type";
+ valid = false;
+ }
+ else {
+ if (argCompCountsSum < targetCompCount) {
+ refCompVals = [];
+ testMsg = "invalid (not enough arguments)";
+ valid = false;
+ }
+ else {
+ // argCompCountsSum >= targetCompCount
+ // All components set
+ var lastArgFirstCompIx = argCompCountsSum - argCompCounts[argCompCounts.length - 1];
+
+ if (lastArgFirstCompIx < targetCompCount) {
+ // First component of last argument is used
+ refCompVals = getArrayWithIncreasingValues(targetCompCount, firstCompValue);
+ testMsg = "valid";
+ valid = true;
+ }
+ else {
+ // First component of last argument is not used
+ refCompVals = [];
+ testMsg = "invalid (unused argument)";
+ valid = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Check if no case is missed
+ if (testMsg == null || valid == null) {
+ wtu.error("GLSLConstructorTestsGenerator.getConstructorExpressionInfo(), info not set");
+ debugger;
+ }
+
+ return {
+ refCompVals: refCompVals,
+ testMsg: testMsg,
+ valid: valid
+ };
+}
+
+
+// Returns a vertex shader testcase and a fragment shader testcase
+function getVertexAndFragmentShaderTestCase(targetType, argExp) {
+ var firstCompValue = 0;
+ if (isGLSLTypeMatrix(targetType)) {
+ // Use value different from 0 and 1
+ // 0 and 1 are values used by matrix constructed from a matrix or a single scalar
+ firstCompValue = 2;
+ }
+
+ var argCode = getTestShaderParts (targetType, argExp, firstCompValue);
+ var expInfo = getConstructorExpressionInfo(targetType, argExp, firstCompValue);
+
+ var substitutions = {
+ type: targetType,
+ errorBound: (getGLSLScalarType(targetType) === "float") ? "const float errorBound = 1.0E-5;" : "",
+ argsList: argCode.argsList,
+ argsConstr: argCode.argsConstr,
+ checkCompVals: getComponentValidationExpression(expInfo.refCompVals, targetType)
+ };
+
+ return [ {
+ // Test constructor argument list in vertex shader
+ vShaderSource: wtu.replaceParams(constructorVertexTemplate, substitutions),
+ vShaderSuccess: expInfo.valid,
+ fShaderSource: passThroughColorFragmentShader,
+ fShaderSuccess: true,
+ linkSuccess: expInfo.valid,
+ passMsg: "Vertex shader : " + argCode.typeExp + ", " + expInfo.testMsg,
+ render: expInfo.valid
+ }, {
+ // Test constructor argument list in fragment shader
+ fShaderSource: wtu.replaceParams(constructorFragmentTemplate, substitutions),
+ fShaderSuccess: expInfo.valid,
+ linkSuccess: expInfo.valid,
+ passMsg: "Fragment shader : " + argCode.typeExp + ", " + expInfo.testMsg,
+ render: expInfo.valid
+ }
+ ];
+}
+
+
+// Incrementing the argument expressions
+// Utility object which defines the order of incrementing the argument types
+var typeCodeIncrementer = {
+ s: { typeCode: "v2", order: 0 },
+ v2: { typeCode: "v3", order: 1 },
+ v3: { typeCode: "v4", order: 2 },
+ v4: { typeCode: "m2", order: 3 },
+ m2: { typeCode: "m3", order: 4 },
+ m3: { typeCode: "m4", order: 5 },
+ m4: { typeCode: "s", order: 6 },
+ first: "s"
+}
+
+
+// Returns the next argument sequence
+function getNextArgumentSequence(inSeq) {
+ var nextSeq;
+ if (inSeq.length === 0) {
+ // Current argument sequence is empty, add first argument
+ nextSeq = [typeCodeIncrementer.first];
+ }
+ else {
+ nextSeq = new Array(inSeq.length);
+ var overflow = true;
+ for (var aa = 0; aa < inSeq.length; ++aa) {
+ var currArg = inSeq[aa];
+ if (overflow) {
+ // Increment the current argument type
+ var nextArg = typeCodeIncrementer[currArg].typeCode;
+ nextSeq[aa] = nextArg;
+ overflow = (nextArg === typeCodeIncrementer.first);
+ }
+ else {
+ // Copy remainder of sequence
+ nextSeq[aa] = currArg;
+ }
+ }
+
+ if (overflow) {
+ nextSeq.push(typeCodeIncrementer.first);
+ }
+ }
+
+ return nextSeq;
+}
+
+
+// Returns true if two argument expressions are equal
+function areArgExpEqual(expA, expB) {
+ if (expA.length !== expB.length)
+ return false;
+
+ for (var aa = 0; aa < expA.length; ++aa)
+ if (expA[aa] !== expB[aa])
+ return false;
+
+ return true;
+}
+
+
+// Returns true if first argument expression is smaller
+// (comes before the second one in iterating order)
+// compared to the second argument expression
+function isArgExpSmallerOrEqual(argExpA, argExpB) {
+ var aLen = argExpA.length;
+ var bLen = argExpB.length;
+ if (aLen !== bLen)
+ return (aLen < bLen);
+
+ // Argument type expression lengths are equal
+ for (var aa = aLen - 1; aa >= 0; --aa) {
+ var argA = argExpA[aa];
+ var argB = argExpB[aa];
+
+ if (argA !== argB) {
+ var aOrder = typeCodeIncrementer[argA].order;
+ var bOrder = typeCodeIncrementer[argB].order;
+ if (aOrder !== bOrder)
+ return (aOrder < bOrder);
+ }
+ }
+
+ // Argument type expressions are equal
+ return true;
+}
+
+
+// Returns the next argument expression from sequence set
+// Returns null if end is reached
+function getNextArgumentExpression(testExp, testSet) {
+ var testInterval = testSet[testExp.ix];
+
+ if (areArgExpEqual(testExp.argExp, testInterval[1])) {
+ // End of current interval reached
+ if (testExp.ix === testSet.length - 1) {
+ // End of set reached
+ return null;
+ }
+ else {
+ // Return first argument expression of next interval
+ var nextIx = testExp.ix + 1;
+ return { ix: nextIx, argExp: testSet[nextIx][0] };
+ }
+ }
+ else {
+ // Return next expression in current interval
+ return { ix: testExp.ix, argExp: getNextArgumentSequence(testExp.argExp) };
+ }
+}
+
+
+// Returns an array of the parts in the string separated by commas and with the white space trimmed
+function convertCsvToArray(str) {
+ // Checks type codes in input
+ function checkInput(el, ix, arr) {
+ var typeCode = el.trim();
+ if (!(typeCode in typeCodeIncrementer) && typeCode !== "first") {
+ wtu.error("GLSLConstructorTestsGenerator.convertCsvToArray(), unknown type code" + typeCode);
+ debugger;
+ }
+
+ arr[ix] = typeCode;
+ }
+
+ var spArr = str.split(",");
+
+ // Convert empty string to empty array
+ if (spArr.length === 1 && spArr[0].trim() === "")
+ spArr = [];
+
+ spArr.forEach(checkInput);
+
+ return spArr;
+}
+
+
+// Processes the set of specified test sequences
+function processInputs(testSequences) {
+ var testSet = new Array(testSequences.length);
+ for (var tt = 0; tt < testSequences.length; ++tt) {
+ var interval = testSequences[tt];
+ var bounds = interval.split("-");
+ var begin = convertCsvToArray(bounds[0]);
+ var end = convertCsvToArray(bounds[bounds.length - 1]);
+
+ // Check if interval is valid
+ if (!isArgExpSmallerOrEqual(begin, end)) {
+ wtu.error("GLSLConstructorTestsGenerator.processInputs(), interval not valid");
+ debugger;
+ }
+
+ testSet[tt] = [ begin, end ];
+ }
+
+ return testSet;
+}
+
+
+/**
+ * Returns list of test cases for vector types
+ * All combinations of arguments up to one unused argument of one component are tested
+ * @param {targetType} Name of target type to test the constructor expressions on
+ * @param {testSet} Set of intervals of argument sequences to test
+ */
+function getConstructorTests(targetType, testSequences) {
+ // List of tests to return
+ var testInfos = [];
+
+ // List of argument types
+ var testSet = processInputs(testSequences);
+ var testExp = { ix: 0, argExp: testSet[0][0] };
+
+ do {
+ // Add one vertex shader test case and one fragment shader test case
+ testInfos = testInfos.concat(getVertexAndFragmentShaderTestCase(targetType, testExp.argExp));
+
+ // Generate next argument expression
+ testExp = getNextArgumentExpression(testExp, testSet);
+ }
+ while (testExp != null);
+
+ return testInfos;
+}
+
+
+// Returns default test argument expression set
+// For details on input format : see bottom of file
+function getDefaultTestSet(targetType) {
+ switch(targetType) {
+ case "vec2":
+ case "ivec2":
+ case "bvec2":
+ return [
+ // No arguments and all single argument expressions
+ " - m4",
+
+ // All two argument expressions with a scalar as second argument
+ "s, s - m4, s",
+
+ // All two arguments expressions with a scalar as first argument
+ "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4",
+
+ // Three argument expression
+ "s, s, s"
+ ];
+
+ case "vec3":
+ case "ivec3":
+ case "bvec3":
+ return [
+ // No arguments and all single argument expressions
+ " - m4",
+
+ // All two argument expressions with a scalar as second argument
+ "s, s - m4, s",
+
+ // All two argument expressions with a scalar as first argument
+ "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4",
+
+ // All three argument expressions with two scalars as second and third argument
+ "s, s, s - m4, s, s",
+
+ // All three argument expressions with two scalars as first and second argument
+ "s, s, v2", "s, s, v3", "s, s, v4", "s, s, m2", "s, s, m3", "s, s, m4",
+
+ // Four argument expression
+ "s, s, s, s"
+ ];
+
+ case "vec4":
+ case "ivec4":
+ case "bvec4":
+ case "mat2":
+ return [
+ // No arguments and all single argument expressions
+ " - m4",
+
+ // All two argument expressions with a scalar as second argument
+ "s, s - m4, s",
+
+ // All two argument expressions with a scalar as first argument
+ "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4",
+
+ // All three argument expressions with two scalars as second and third argument
+ "s, s, s - m4, s, s",
+
+ // All three argument expressions with two scalars as first and second argument
+ "s, s, v2", "s, s, v3", "s, s, v4", "s, s, m2", "s, s, m3", "s, s, m4",
+
+ // All four argument expressions with three scalars as second, third and fourth argument
+ "s, s, s, s - m4, s, s, s",
+
+ // All four argument expressions with three scalars as first, second and third argument
+ "s, s, s, v2", "s, s, s, v3", "s, s, s, v4", "s, s, s, m2", "s, s, s, m3", "s, s, s, m4",
+
+ // Five argument expression
+ "s, s, s, s, s"
+ ];
+
+ case "mat3":
+ case "mat4":
+ return [
+ // No arguments and all single argument expressions
+ " - m4",
+
+ // All two argument expressions with a scalar as second argument
+ "s, s - m4, s",
+
+ // All two argument expressions with a scalar as first argument
+ "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4",
+
+ // Several argument sequences
+ "v4, s, v4", "v4, s, v3, v2", "v4, v4, v3, v2", "v4, v4, v4, v4", "v2, v2, v2, v2, v2", "v2, v2, v2, v2, v2, v2, v2, v2",
+ "v3, v3, v3", "v3, v3, v3, s", "v3, v3, v3, v3, v3, s", "v3, v3, v3, v3, v3, s, s",
+ ];
+ }
+}
+
+
+// Return publics
+return {
+ getConstructorTests: getConstructorTests,
+ getDefaultTestSet: getDefaultTestSet
+};
+
+}());
+
+
+// Input is an array of intervals of argument types
+// The generated test argument sequences are from (including) the lower interval boundary
+// until (including) the upper boundary
+// Coding and order of the different argument types :
+// s : scalar
+// v2 : vec2
+// v3 : vec3
+// v4 : vec4
+// m2 : mat2
+// m3 : mat3
+// m4 : mat4
+
+// One interval is put in one string
+// Low and high bound are separated by a dash.
+// If there is no dash it is regarded as an interval of one expression
+// The individual argument codes are separated by commas
+// The individual arguments are incremented from left to right
+// The left most argument is the one which is incremented first
+// Once the left most arguments wraps the second argument is increased
+// Examples :
+// "s - m4" : All single arguments from scalar up to (including) mat4
+// "m2, s - m4, s" : All two argument expressions with a matrix argument as first argument and a scalar as second argument
+// " - m4, m4" : The empty argument, all one arguments and all two argument expressions
+// "m2, s, v3, m4" : One 4 argument expression : mat2, scalar, vec3, mat4
diff --git a/dom/canvas/test/webgl-conf/checkout/js/glsl-generator.js b/dom/canvas/test/webgl-conf/checkout/js/glsl-generator.js
new file mode 100644
index 000000000..dbb97eb02
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/glsl-generator.js
@@ -0,0 +1,1251 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+GLSLGenerator = (function() {
+
+var vertexShaderTemplate = [
+ "attribute vec4 aPosition;",
+ "",
+ "varying vec4 vColor;",
+ "",
+ "$(extra)",
+ "$(emu)",
+ "",
+ "void main()",
+ "{",
+ " gl_Position = aPosition;",
+ " vec2 texcoord = vec2(aPosition.xy * 0.5 + vec2(0.5, 0.5));",
+ " vec4 color = vec4(",
+ " texcoord,",
+ " texcoord.x * texcoord.y,",
+ " (1.0 - texcoord.x) * texcoord.y * 0.5 + 0.5);",
+ " $(test)",
+ "}"
+].join("\n");
+
+var fragmentShaderTemplate = [
+ "precision mediump float;",
+ "",
+ "varying vec4 vColor;",
+ "",
+ "$(extra)",
+ "$(emu)",
+ "",
+ "void main()",
+ "{",
+ " $(test)",
+ "}"
+].join("\n");
+
+var baseVertexShader = [
+ "attribute vec4 aPosition;",
+ "",
+ "varying vec4 vColor;",
+ "",
+ "void main()",
+ "{",
+ " gl_Position = aPosition;",
+ " vec2 texcoord = vec2(aPosition.xy * 0.5 + vec2(0.5, 0.5));",
+ " vColor = vec4(",
+ " texcoord,",
+ " texcoord.x * texcoord.y,",
+ " (1.0 - texcoord.x) * texcoord.y * 0.5 + 0.5);",
+ "}"
+].join("\n");
+
+var baseVertexShaderWithColor = [
+ "attribute vec4 aPosition;",
+ "attribute vec4 aColor;",
+ "",
+ "varying vec4 vColor;",
+ "",
+ "void main()",
+ "{",
+ " gl_Position = aPosition;",
+ " vColor = aColor;",
+ "}"
+].join("\n");
+
+var baseFragmentShader = [
+ "precision mediump float;",
+ "varying vec4 vColor;",
+ "",
+ "void main()",
+ "{",
+ " gl_FragColor = vColor;",
+ "}"
+].join("\n");
+
+var types = [
+ { type: "float",
+ code: [
+ "float $(func)_emu($(args)) {",
+ " return $(func)_base($(baseArgs));",
+ "}"].join("\n")
+ },
+ { type: "vec2",
+ code: [
+ "vec2 $(func)_emu($(args)) {",
+ " return vec2(",
+ " $(func)_base($(baseArgsX)),",
+ " $(func)_base($(baseArgsY)));",
+ "}"].join("\n")
+ },
+ { type: "vec3",
+ code: [
+ "vec3 $(func)_emu($(args)) {",
+ " return vec3(",
+ " $(func)_base($(baseArgsX)),",
+ " $(func)_base($(baseArgsY)),",
+ " $(func)_base($(baseArgsZ)));",
+ "}"].join("\n")
+ },
+ { type: "vec4",
+ code: [
+ "vec4 $(func)_emu($(args)) {",
+ " return vec4(",
+ " $(func)_base($(baseArgsX)),",
+ " $(func)_base($(baseArgsY)),",
+ " $(func)_base($(baseArgsZ)),",
+ " $(func)_base($(baseArgsW)));",
+ "}"].join("\n")
+ }
+];
+
+var bvecTypes = [
+ { type: "bvec2",
+ code: [
+ "bvec2 $(func)_emu($(args)) {",
+ " return bvec2(",
+ " $(func)_base($(baseArgsX)),",
+ " $(func)_base($(baseArgsY)));",
+ "}"].join("\n")
+ },
+ { type: "bvec3",
+ code: [
+ "bvec3 $(func)_emu($(args)) {",
+ " return bvec3(",
+ " $(func)_base($(baseArgsX)),",
+ " $(func)_base($(baseArgsY)),",
+ " $(func)_base($(baseArgsZ)));",
+ "}"].join("\n")
+ },
+ { type: "bvec4",
+ code: [
+ "vec4 $(func)_emu($(args)) {",
+ " return bvec4(",
+ " $(func)_base($(baseArgsX)),",
+ " $(func)_base($(baseArgsY)),",
+ " $(func)_base($(baseArgsZ)),",
+ " $(func)_base($(baseArgsW)));",
+ "}"].join("\n")
+ }
+];
+
+var replaceRE = /\$\((\w+)\)/g;
+
+var replaceParams = function(str) {
+ var args = arguments;
+ return str.replace(replaceRE, function(str, p1, offset, s) {
+ for (var ii = 1; ii < args.length; ++ii) {
+ if (args[ii][p1] !== undefined) {
+ return args[ii][p1];
+ }
+ }
+ throw "unknown string param '" + p1 + "'";
+ });
+};
+
+var generateReferenceShader = function(
+ shaderInfo, template, params, typeInfo, test) {
+ var input = shaderInfo.input;
+ var output = shaderInfo.output;
+ var feature = params.feature;
+ var testFunc = params.testFunc;
+ var emuFunc = params.emuFunc || "";
+ var extra = params.extra || '';
+ var args = params.args || "$(type) value";
+ var type = typeInfo.type;
+ var typeCode = typeInfo.code;
+
+ var baseArgs = params.baseArgs || "value$(field)";
+ var baseArgsX = replaceParams(baseArgs, {field: ".x"});
+ var baseArgsY = replaceParams(baseArgs, {field: ".y"});
+ var baseArgsZ = replaceParams(baseArgs, {field: ".z"});
+ var baseArgsW = replaceParams(baseArgs, {field: ".w"});
+ var baseArgs = replaceParams(baseArgs, {field: ""});
+
+ test = replaceParams(test, {
+ input: input,
+ output: output,
+ func: feature + "_emu"
+ });
+ emuFunc = replaceParams(emuFunc, {
+ func: feature
+ });
+ args = replaceParams(args, {
+ type: type
+ });
+ typeCode = replaceParams(typeCode, {
+ func: feature,
+ type: type,
+ args: args,
+ baseArgs: baseArgs,
+ baseArgsX: baseArgsX,
+ baseArgsY: baseArgsY,
+ baseArgsZ: baseArgsZ,
+ baseArgsW: baseArgsW
+ });
+ var shader = replaceParams(template, {
+ extra: extra,
+ emu: emuFunc + "\n\n" + typeCode,
+ test: test
+ });
+ return shader;
+};
+
+var generateTestShader = function(
+ shaderInfo, template, params, test) {
+ var input = shaderInfo.input;
+ var output = shaderInfo.output;
+ var feature = params.feature;
+ var testFunc = params.testFunc;
+ var extra = params.extra || '';
+
+ test = replaceParams(test, {
+ input: input,
+ output: output,
+ func: feature
+ });
+ var shader = replaceParams(template, {
+ extra: extra,
+ emu: '',
+ test: test
+ });
+ return shader;
+};
+
+function _reportResults(refData, refImg, testData, testImg, tolerance,
+ width, height, ctx, imgData, wtu, canvas2d, consoleDiv) {
+ var same = true;
+ var firstFailure = null;
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var offset = (yy * width + xx) * 4;
+ var imgOffset = ((height - yy - 1) * width + xx) * 4;
+ imgData.data[imgOffset + 0] = 0;
+ imgData.data[imgOffset + 1] = 0;
+ imgData.data[imgOffset + 2] = 0;
+ imgData.data[imgOffset + 3] = 255;
+ if (Math.abs(refData[offset + 0] - testData[offset + 0]) > tolerance ||
+ Math.abs(refData[offset + 1] - testData[offset + 1]) > tolerance ||
+ Math.abs(refData[offset + 2] - testData[offset + 2]) > tolerance ||
+ Math.abs(refData[offset + 3] - testData[offset + 3]) > tolerance) {
+ var detail = 'at (' + xx + ',' + yy + '): ref=(' +
+ refData[offset + 0] + ',' +
+ refData[offset + 1] + ',' +
+ refData[offset + 2] + ',' +
+ refData[offset + 3] + ') test=(' +
+ testData[offset + 0] + ',' +
+ testData[offset + 1] + ',' +
+ testData[offset + 2] + ',' +
+ testData[offset + 3] + ') tolerance=' + tolerance;
+ consoleDiv.appendChild(document.createTextNode(detail));
+ consoleDiv.appendChild(document.createElement('br'));
+ if (!firstFailure) {
+ firstFailure = ": " + detail;
+ }
+ imgData.data[imgOffset] = 255;
+ same = false;
+ }
+ }
+ }
+
+ var diffImg = null;
+ if (!same) {
+ ctx.putImageData(imgData, 0, 0);
+ diffImg = wtu.makeImageFromCanvas(canvas2d);
+ }
+
+ var div = document.createElement("div");
+ div.className = "testimages";
+ wtu.insertImage(div, "ref", refImg);
+ wtu.insertImage(div, "test", testImg);
+ if (diffImg) {
+ wtu.insertImage(div, "diff", diffImg);
+ }
+ div.appendChild(document.createElement('br'));
+
+ consoleDiv.appendChild(div);
+
+ if (!same) {
+ testFailed("images are different" + (firstFailure ? firstFailure : ""));
+ } else {
+ testPassed("images are the same");
+ }
+
+ consoleDiv.appendChild(document.createElement('hr'));
+}
+
+var runFeatureTest = function(params) {
+ var wtu = WebGLTestUtils;
+ var gridRes = params.gridRes;
+ var vertexTolerance = params.tolerance || 0;
+ var fragmentTolerance = params.tolerance || 1;
+ if ('fragmentTolerance' in params)
+ fragmentTolerance = params.fragmentTolerance;
+
+ description("Testing GLSL feature: " + params.feature);
+
+ var width = 32;
+ var height = 32;
+
+ var consoleDiv = document.getElementById("console");
+ var canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ var gl = wtu.create3DContext(canvas, { premultipliedAlpha: false });
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+
+ var canvas2d = document.createElement('canvas');
+ canvas2d.width = width;
+ canvas2d.height = height;
+ var ctx = canvas2d.getContext("2d");
+ var imgData = ctx.getImageData(0, 0, width, height);
+
+ var shaderInfos = [
+ { type: "vertex",
+ input: "color",
+ output: "vColor",
+ vertexShaderTemplate: vertexShaderTemplate,
+ fragmentShaderTemplate: baseFragmentShader,
+ tolerance: vertexTolerance
+ },
+ { type: "fragment",
+ input: "vColor",
+ output: "gl_FragColor",
+ vertexShaderTemplate: baseVertexShader,
+ fragmentShaderTemplate: fragmentShaderTemplate,
+ tolerance: fragmentTolerance
+ }
+ ];
+ for (var ss = 0; ss < shaderInfos.length; ++ss) {
+ var shaderInfo = shaderInfos[ss];
+ var tests = params.tests;
+ var testTypes = params.emuFuncs || (params.bvecTest ? bvecTypes : types);
+ // Test vertex shaders
+ for (var ii = 0; ii < tests.length; ++ii) {
+ var type = testTypes[ii];
+ if (params.simpleEmu) {
+ type = {
+ type: type.type,
+ code: params.simpleEmu
+ };
+ }
+ debug("");
+ var str = replaceParams(params.testFunc, {
+ func: params.feature,
+ type: type.type,
+ arg0: type.type
+ });
+ var passMsg = "Testing: " + str + " in " + shaderInfo.type + " shader";
+ debug(passMsg);
+
+ var referenceVertexShaderSource = generateReferenceShader(
+ shaderInfo,
+ shaderInfo.vertexShaderTemplate,
+ params,
+ type,
+ tests[ii]);
+ var referenceFragmentShaderSource = generateReferenceShader(
+ shaderInfo,
+ shaderInfo.fragmentShaderTemplate,
+ params,
+ type,
+ tests[ii]);
+ var testVertexShaderSource = generateTestShader(
+ shaderInfo,
+ shaderInfo.vertexShaderTemplate,
+ params,
+ tests[ii]);
+ var testFragmentShaderSource = generateTestShader(
+ shaderInfo,
+ shaderInfo.fragmentShaderTemplate,
+ params,
+ tests[ii]);
+
+
+ debug("");
+ var referenceVertexShader = wtu.loadShader(gl, referenceVertexShaderSource, gl.VERTEX_SHADER, testFailed, true, 'reference');
+ var referenceFragmentShader = wtu.loadShader(gl, referenceFragmentShaderSource, gl.FRAGMENT_SHADER, testFailed, true, 'reference');
+ var testVertexShader = wtu.loadShader(gl, testVertexShaderSource, gl.VERTEX_SHADER, testFailed, true, 'test');
+ var testFragmentShader = wtu.loadShader(gl, testFragmentShaderSource, gl.FRAGMENT_SHADER, testFailed, true, 'test');
+ debug("");
+
+ if (parseInt(wtu.getUrlOptions().dumpShaders)) {
+ var vRefInfo = {
+ shader: referenceVertexShader,
+ shaderSuccess: true,
+ label: "reference vertex shader",
+ source: referenceVertexShaderSource
+ };
+ var fRefInfo = {
+ shader: referenceFragmentShader,
+ shaderSuccess: true,
+ label: "reference fragment shader",
+ source: referenceFragmentShaderSource
+ };
+ wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vRefInfo, fRefInfo);
+
+ var vTestInfo = {
+ shader: testVertexShader,
+ shaderSuccess: true,
+ label: "test vertex shader",
+ source: testVertexShaderSource
+ };
+ var fTestInfo = {
+ shader: testFragmentShader,
+ shaderSuccess: true,
+ label: "test fragment shader",
+ source: testFragmentShaderSource
+ };
+ wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vTestInfo, fTestInfo);
+ }
+
+ var refData = draw(
+ referenceVertexShader, referenceFragmentShader);
+ var refImg = wtu.makeImageFromCanvas(canvas);
+ if (ss == 0) {
+ var testData = draw(
+ testVertexShader, referenceFragmentShader);
+ } else {
+ var testData = draw(
+ referenceVertexShader, testFragmentShader);
+ }
+ var testImg = wtu.makeImageFromCanvas(canvas);
+
+ _reportResults(refData, refImg, testData, testImg, shaderInfo.tolerance,
+ width, height, ctx, imgData, wtu, canvas2d, consoleDiv);
+ }
+ }
+
+ finishTest();
+
+ function draw(vertexShader, fragmentShader) {
+ var program = wtu.createProgram(gl, vertexShader, fragmentShader, testFailed);
+
+ var posLoc = gl.getAttribLocation(program, "aPosition");
+ wtu.setupIndexedQuad(gl, gridRes, posLoc);
+
+ gl.useProgram(program);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes, [0, 0, 255, 255]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+
+ var img = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ return img;
+ }
+
+};
+
+var runBasicTest = function(params) {
+ var wtu = WebGLTestUtils;
+ var gridRes = params.gridRes;
+ var vertexTolerance = params.tolerance || 0;
+ var fragmentTolerance = vertexTolerance;
+ if ('fragmentTolerance' in params)
+ fragmentTolerance = params.fragmentTolerance || 0;
+
+ description("Testing : " + document.getElementsByTagName("title")[0].innerText);
+
+ var width = 32;
+ var height = 32;
+
+ var consoleDiv = document.getElementById("console");
+ var canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ var gl = wtu.create3DContext(canvas);
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+
+ var canvas2d = document.createElement('canvas');
+ canvas2d.width = width;
+ canvas2d.height = height;
+ var ctx = canvas2d.getContext("2d");
+ var imgData = ctx.getImageData(0, 0, width, height);
+
+ var shaderInfos = [
+ { type: "vertex",
+ input: "color",
+ output: "vColor",
+ vertexShaderTemplate: vertexShaderTemplate,
+ fragmentShaderTemplate: baseFragmentShader,
+ tolerance: vertexTolerance
+ },
+ { type: "fragment",
+ input: "vColor",
+ output: "gl_FragColor",
+ vertexShaderTemplate: baseVertexShader,
+ fragmentShaderTemplate: fragmentShaderTemplate,
+ tolerance: fragmentTolerance
+ }
+ ];
+ for (var ss = 0; ss < shaderInfos.length; ++ss) {
+ var shaderInfo = shaderInfos[ss];
+ var tests = params.tests;
+// var testTypes = params.emuFuncs || (params.bvecTest ? bvecTypes : types);
+ // Test vertex shaders
+ for (var ii = 0; ii < tests.length; ++ii) {
+ var test = tests[ii];
+ debug("");
+ var passMsg = "Testing: " + test.name + " in " + shaderInfo.type + " shader";
+ debug(passMsg);
+
+ function genShader(shaderInfo, template, shader, subs) {
+ shader = replaceParams(shader, subs, {
+ input: shaderInfo.input,
+ output: shaderInfo.output
+ });
+ shader = replaceParams(template, subs, {
+ test: shader,
+ emu: "",
+ extra: ""
+ });
+ return shader;
+ }
+
+ var referenceVertexShaderSource = genShader(
+ shaderInfo,
+ shaderInfo.vertexShaderTemplate,
+ test.reference.shader,
+ test.reference.subs);
+ var referenceFragmentShaderSource = genShader(
+ shaderInfo,
+ shaderInfo.fragmentShaderTemplate,
+ test.reference.shader,
+ test.reference.subs);
+ var testVertexShaderSource = genShader(
+ shaderInfo,
+ shaderInfo.vertexShaderTemplate,
+ test.test.shader,
+ test.test.subs);
+ var testFragmentShaderSource = genShader(
+ shaderInfo,
+ shaderInfo.fragmentShaderTemplate,
+ test.test.shader,
+ test.test.subs);
+
+ debug("");
+ var referenceVertexShader = wtu.loadShader(gl, referenceVertexShaderSource, gl.VERTEX_SHADER, testFailed, true, 'reference');
+ var referenceFragmentShader = wtu.loadShader(gl, referenceFragmentShaderSource, gl.FRAGMENT_SHADER, testFailed, true, 'reference');
+ var testVertexShader = wtu.loadShader(gl, testVertexShaderSource, gl.VERTEX_SHADER, testFailed, true, 'test');
+ var testFragmentShader = wtu.loadShader(gl, testFragmentShaderSource, gl.FRAGMENT_SHADER, testFailed, true, 'test');
+ debug("");
+
+ if (parseInt(wtu.getUrlOptions().dumpShaders)) {
+ var vRefInfo = {
+ shader: referenceVertexShader,
+ shaderSuccess: true,
+ label: "reference vertex shader",
+ source: referenceVertexShaderSource
+ };
+ var fRefInfo = {
+ shader: referenceFragmentShader,
+ shaderSuccess: true,
+ label: "reference fragment shader",
+ source: referenceFragmentShaderSource
+ };
+ wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vRefInfo, fRefInfo);
+
+ var vTestInfo = {
+ shader: testVertexShader,
+ shaderSuccess: true,
+ label: "test vertex shader",
+ source: testVertexShaderSource
+ };
+ var fTestInfo = {
+ shader: testFragmentShader,
+ shaderSuccess: true,
+ label: "test fragment shader",
+ source: testFragmentShaderSource
+ };
+ wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vTestInfo, fTestInfo);
+ }
+
+ var refData = draw(referenceVertexShader, referenceFragmentShader);
+ var refImg = wtu.makeImageFromCanvas(canvas);
+ if (ss == 0) {
+ var testData = draw(testVertexShader, referenceFragmentShader);
+ } else {
+ var testData = draw(referenceVertexShader, testFragmentShader);
+ }
+ var testImg = wtu.makeImageFromCanvas(canvas);
+
+ _reportResults(refData, refImg, testData, testImg, shaderInfo.tolerance,
+ width, height, ctx, imgData, wtu, canvas2d, consoleDiv);
+ }
+ }
+
+ finishTest();
+
+ function draw(vertexShader, fragmentShader) {
+ var program = wtu.createProgram(gl, vertexShader, fragmentShader, testFailed);
+
+ var posLoc = gl.getAttribLocation(program, "aPosition");
+ wtu.setupIndexedQuad(gl, gridRes, posLoc);
+
+ gl.useProgram(program);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes, [0, 0, 255, 255]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+
+ var img = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ return img;
+ }
+
+};
+
+var runReferenceImageTest = function(params) {
+ var wtu = WebGLTestUtils;
+ var gridRes = params.gridRes;
+ var vertexTolerance = params.tolerance || 0;
+ var fragmentTolerance = vertexTolerance;
+ if ('fragmentTolerance' in params)
+ fragmentTolerance = params.fragmentTolerance || 0;
+
+ description("Testing GLSL feature: " + params.feature);
+
+ var width = 32;
+ var height = 32;
+
+ var consoleDiv = document.getElementById("console");
+ var canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ var gl = wtu.create3DContext(canvas, { antialias: false, premultipliedAlpha: false });
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+
+ var canvas2d = document.createElement('canvas');
+ canvas2d.width = width;
+ canvas2d.height = height;
+ var ctx = canvas2d.getContext("2d");
+ var imgData = ctx.getImageData(0, 0, width, height);
+
+ // State for reference images for vertex shader tests.
+ // These are drawn with the same tessellated grid as the test vertex
+ // shader so that the interpolation is identical. The grid is reused
+ // from test to test; the colors are changed.
+
+ var indexedQuadForReferenceVertexShader =
+ wtu.setupIndexedQuad(gl, gridRes, 0);
+ var referenceVertexShaderProgram =
+ wtu.setupProgram(gl, [ baseVertexShaderWithColor, baseFragmentShader ],
+ ["aPosition", "aColor"]);
+ var referenceVertexShaderColorBuffer = gl.createBuffer();
+
+ var shaderInfos = [
+ { type: "vertex",
+ input: "color",
+ output: "vColor",
+ vertexShaderTemplate: vertexShaderTemplate,
+ fragmentShaderTemplate: baseFragmentShader,
+ tolerance: vertexTolerance
+ },
+ { type: "fragment",
+ input: "vColor",
+ output: "gl_FragColor",
+ vertexShaderTemplate: baseVertexShader,
+ fragmentShaderTemplate: fragmentShaderTemplate,
+ tolerance: fragmentTolerance
+ }
+ ];
+ for (var ss = 0; ss < shaderInfos.length; ++ss) {
+ var shaderInfo = shaderInfos[ss];
+ var tests = params.tests;
+ var testTypes = params.emuFuncs || (params.bvecTest ? bvecTypes : types);
+ // Test vertex shaders
+ for (var ii = 0; ii < tests.length; ++ii) {
+ var type = testTypes[ii];
+ var isVertex = (ss == 0);
+ debug("");
+ var str = replaceParams(params.testFunc, {
+ func: params.feature,
+ type: type.type,
+ arg0: type.type
+ });
+ var passMsg = "Testing: " + str + " in " + shaderInfo.type + " shader";
+ debug(passMsg);
+
+ var referenceVertexShaderSource = generateReferenceShader(
+ shaderInfo,
+ shaderInfo.vertexShaderTemplate,
+ params,
+ type,
+ tests[ii].source);
+ var referenceFragmentShaderSource = generateReferenceShader(
+ shaderInfo,
+ shaderInfo.fragmentShaderTemplate,
+ params,
+ type,
+ tests[ii].source);
+ var testVertexShaderSource = generateTestShader(
+ shaderInfo,
+ shaderInfo.vertexShaderTemplate,
+ params,
+ tests[ii].source);
+ var testFragmentShaderSource = generateTestShader(
+ shaderInfo,
+ shaderInfo.fragmentShaderTemplate,
+ params,
+ tests[ii].source);
+ var referenceTextureOrArray = generateReferenceImage(
+ gl,
+ tests[ii].generator,
+ isVertex ? gridRes : width,
+ isVertex ? gridRes : height,
+ isVertex);
+
+ debug("");
+ var testVertexShader = wtu.loadShader(gl, testVertexShaderSource, gl.VERTEX_SHADER, testFailed, true);
+ var testFragmentShader = wtu.loadShader(gl, testFragmentShaderSource, gl.FRAGMENT_SHADER, testFailed, true);
+ debug("");
+
+
+ if (parseInt(wtu.getUrlOptions().dumpShaders)) {
+ var vRefInfo = {
+ shader: referenceVertexShader,
+ shaderSuccess: true,
+ label: "reference vertex shader",
+ source: referenceVertexShaderSource
+ };
+ var fRefInfo = {
+ shader: referenceFragmentShader,
+ shaderSuccess: true,
+ label: "reference fragment shader",
+ source: referenceFragmentShaderSource
+ };
+ wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vRefInfo, fRefInfo);
+
+ var vTestInfo = {
+ shader: testVertexShader,
+ shaderSuccess: true,
+ label: "test vertex shader",
+ source: testVertexShaderSource
+ };
+ var fTestInfo = {
+ shader: testFragmentShader,
+ shaderSuccess: true,
+ label: "test fragment shader",
+ source: testFragmentShaderSource
+ };
+ wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vTestInfo, fTestInfo);
+ }
+
+ var refData;
+ if (isVertex) {
+ refData = drawVertexReferenceImage(referenceTextureOrArray);
+ } else {
+ refData = drawFragmentReferenceImage(referenceTextureOrArray);
+ }
+ var refImg = wtu.makeImageFromCanvas(canvas);
+ var testData;
+ if (isVertex) {
+ var referenceFragmentShader = wtu.loadShader(gl, referenceFragmentShaderSource, gl.FRAGMENT_SHADER, testFailed);
+ testData = draw(
+ testVertexShader, referenceFragmentShader);
+ } else {
+ var referenceVertexShader = wtu.loadShader(gl, referenceVertexShaderSource, gl.VERTEX_SHADER, testFailed);
+ testData = draw(
+ referenceVertexShader, testFragmentShader);
+ }
+ var testImg = wtu.makeImageFromCanvas(canvas);
+ var testTolerance = shaderInfo.tolerance;
+ // Provide per-test tolerance so that we can increase it only for those desired.
+ if ('tolerance' in tests[ii])
+ testTolerance = tests[ii].tolerance || 0;
+ _reportResults(refData, refImg, testData, testImg, testTolerance,
+ width, height, ctx, imgData, wtu, canvas2d, consoleDiv);
+ }
+ }
+
+ finishTest();
+
+ function draw(vertexShader, fragmentShader) {
+ var program = wtu.createProgram(gl, vertexShader, fragmentShader, testFailed);
+
+ var posLoc = gl.getAttribLocation(program, "aPosition");
+ wtu.setupIndexedQuad(gl, gridRes, posLoc);
+
+ gl.useProgram(program);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes, [0, 0, 255, 255]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+
+ var img = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ return img;
+ }
+
+ function drawVertexReferenceImage(colors) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, indexedQuadForReferenceVertexShader[0]);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, referenceVertexShaderColorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexedQuadForReferenceVertexShader[1]);
+ gl.useProgram(referenceVertexShaderProgram);
+ wtu.clearAndDrawIndexedQuad(gl, gridRes);
+ gl.disableVertexAttribArray(0);
+ gl.disableVertexAttribArray(1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+
+ var img = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ return img;
+ }
+
+ function drawFragmentReferenceImage(texture) {
+ var program = wtu.setupTexturedQuad(gl);
+
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ var texLoc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(texLoc, 0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
+
+ var img = new Uint8Array(width * height * 4);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
+ return img;
+ }
+
+ /**
+ * Creates and returns either a Uint8Array (for vertex shaders) or
+ * WebGLTexture (for fragment shaders) containing the reference
+ * image for the function being tested. Exactly how the function is
+ * evaluated, and the size of the returned texture or array, depends on
+ * whether we are testing a vertex or fragment shader. If a fragment
+ * shader, the function is evaluated at the pixel centers. If a
+ * vertex shader, the function is evaluated at the triangle's
+ * vertices.
+ *
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use to generate texture objects.
+ * @param {!function(number,number,number,number): !Array.<number>} generator The reference image generator function.
+ * @param {number} width The width of the texture to generate if testing a fragment shader; the grid resolution if testing a vertex shader.
+ * @param {number} height The height of the texture to generate if testing a fragment shader; the grid resolution if testing a vertex shader.
+ * @param {boolean} isVertex True if generating a reference image for a vertex shader; false if for a fragment shader.
+ * @return {!WebGLTexture|!Uint8Array} The texture object or array that was generated.
+ */
+ function generateReferenceImage(
+ gl,
+ generator,
+ width,
+ height,
+ isVertex) {
+
+ // Note: the math in this function must match that in the vertex and
+ // fragment shader templates above.
+ function computeTexCoord(x) {
+ return x * 0.5 + 0.5;
+ }
+
+ function computeVertexColor(texCoordX, texCoordY) {
+ return [ texCoordX,
+ texCoordY,
+ texCoordX * texCoordY,
+ (1.0 - texCoordX) * texCoordY * 0.5 + 0.5 ];
+ }
+
+ /**
+ * Computes fragment color according to the algorithm used for interpolation
+ * in OpenGL (GLES 2.0 spec 3.5.1, OpenGL 4.3 spec 14.6.1).
+ */
+ function computeInterpolatedColor(texCoordX, texCoordY) {
+ // Calculate grid line indexes below and to the left from texCoord.
+ var gridBottom = Math.floor(texCoordY * gridRes);
+ if (gridBottom == gridRes) {
+ --gridBottom;
+ }
+ var gridLeft = Math.floor(texCoordX * gridRes);
+ if (gridLeft == gridRes) {
+ --gridLeft;
+ }
+
+ // Calculate coordinates relative to the grid cell.
+ var cellX = texCoordX * gridRes - gridLeft;
+ var cellY = texCoordY * gridRes - gridBottom;
+
+ // Barycentric coordinates inside either triangle ACD or ABC
+ // are used as weights for the vertex colors in the corners:
+ // A--B
+ // |\ |
+ // | \|
+ // D--C
+
+ var aColor = computeVertexColor(gridLeft / gridRes, (gridBottom + 1) / gridRes);
+ var bColor = computeVertexColor((gridLeft + 1) / gridRes, (gridBottom + 1) / gridRes);
+ var cColor = computeVertexColor((gridLeft + 1) / gridRes, gridBottom / gridRes);
+ var dColor = computeVertexColor(gridLeft / gridRes, gridBottom / gridRes);
+
+ // Calculate weights.
+ var a, b, c, d;
+
+ if (cellX + cellY < 1) {
+ // In bottom triangle ACD.
+ a = cellY; // area of triangle C-D-(cellX, cellY) relative to ACD
+ c = cellX; // area of triangle D-A-(cellX, cellY) relative to ACD
+ d = 1 - a - c;
+ b = 0;
+ } else {
+ // In top triangle ABC.
+ a = 1 - cellX; // area of the triangle B-C-(cellX, cellY) relative to ABC
+ c = 1 - cellY; // area of the triangle A-B-(cellX, cellY) relative to ABC
+ b = 1 - a - c;
+ d = 0;
+ }
+
+ var interpolated = [];
+ for (var ii = 0; ii < aColor.length; ++ii) {
+ interpolated.push(a * aColor[ii] + b * bColor[ii] + c * cColor[ii] + d * dColor[ii]);
+ }
+ return interpolated;
+ }
+
+ function clamp(value, minVal, maxVal) {
+ return Math.max(minVal, Math.min(value, maxVal));
+ }
+
+ // Evaluates the function at clip coordinates (px,py), storing the
+ // result in the array "pixel". Each channel's result is clamped
+ // between 0 and 255.
+ function evaluateAtClipCoords(px, py, pixel, colorFunc) {
+ var tcx = computeTexCoord(px);
+ var tcy = computeTexCoord(py);
+
+ var color = colorFunc(tcx, tcy);
+
+ var output = generator(color[0], color[1], color[2], color[3]);
+
+ // Multiply by 256 to get even distribution for all values between 0 and 1.
+ // Use rounding rather than truncation to more closely match the GPU's behavior.
+ pixel[0] = clamp(Math.round(256 * output[0]), 0, 255);
+ pixel[1] = clamp(Math.round(256 * output[1]), 0, 255);
+ pixel[2] = clamp(Math.round(256 * output[2]), 0, 255);
+ pixel[3] = clamp(Math.round(256 * output[3]), 0, 255);
+ }
+
+ function generateFragmentReference() {
+ var data = new Uint8Array(4 * width * height);
+
+ var horizTexel = 1.0 / width;
+ var vertTexel = 1.0 / height;
+ var halfHorizTexel = 0.5 * horizTexel;
+ var halfVertTexel = 0.5 * vertTexel;
+
+ var pixel = new Array(4);
+
+ for (var yi = 0; yi < height; ++yi) {
+ for (var xi = 0; xi < width; ++xi) {
+ // The function must be evaluated at pixel centers.
+
+ // Compute desired position in clip space
+ var px = -1.0 + 2.0 * (halfHorizTexel + xi * horizTexel);
+ var py = -1.0 + 2.0 * (halfVertTexel + yi * vertTexel);
+
+ evaluateAtClipCoords(px, py, pixel, computeInterpolatedColor);
+ var index = 4 * (width * yi + xi);
+ data[index + 0] = pixel[0];
+ data[index + 1] = pixel[1];
+ data[index + 2] = pixel[2];
+ data[index + 3] = pixel[3];
+ }
+ }
+
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, data);
+ return texture;
+ }
+
+ function generateVertexReference() {
+ // We generate a Uint8Array which contains the evaluation of the
+ // function at the vertices of the triangle mesh. It is expected
+ // that the width and the height are identical, and equivalent
+ // to the grid resolution.
+ if (width != height) {
+ throw "width and height must be equal";
+ }
+
+ var texSize = 1 + width;
+ var data = new Uint8Array(4 * texSize * texSize);
+
+ var step = 2.0 / width;
+
+ var pixel = new Array(4);
+
+ for (var yi = 0; yi < texSize; ++yi) {
+ for (var xi = 0; xi < texSize; ++xi) {
+ // The function is evaluated at the triangles' vertices.
+
+ // Compute desired position in clip space
+ var px = -1.0 + (xi * step);
+ var py = -1.0 + (yi * step);
+
+ evaluateAtClipCoords(px, py, pixel, computeVertexColor);
+ var index = 4 * (texSize * yi + xi);
+ data[index + 0] = pixel[0];
+ data[index + 1] = pixel[1];
+ data[index + 2] = pixel[2];
+ data[index + 3] = pixel[3];
+ }
+ }
+
+ return data;
+ }
+
+ //----------------------------------------------------------------------
+ // Body of generateReferenceImage
+ //
+
+ if (isVertex) {
+ return generateVertexReference();
+ } else {
+ return generateFragmentReference();
+ }
+ }
+};
+
+return {
+ /**
+ * runs a bunch of GLSL tests using the passed in parameters
+ * The parameters are:
+ *
+ * feature:
+ * the name of the function being tested (eg, sin, dot,
+ * normalize)
+ *
+ * testFunc:
+ * The prototype of function to be tested not including the
+ * return type.
+ *
+ * emuFunc:
+ * A base function that can be used to generate emulation
+ * functions. Example for 'ceil'
+ *
+ * float $(func)_base(float value) {
+ * float m = mod(value, 1.0);
+ * return m != 0.0 ? (value + 1.0 - m) : value;
+ * }
+ *
+ * args:
+ * The arguments to the function
+ *
+ * baseArgs: (optional)
+ * The arguments when a base function is used to create an
+ * emulation function. For example 'float sign_base(float v)'
+ * is used to implemenent vec2 sign_emu(vec2 v).
+ *
+ * simpleEmu:
+ * if supplied, the code that can be used to generate all
+ * functions for all types.
+ *
+ * Example for 'normalize':
+ *
+ * $(type) $(func)_emu($(args)) {
+ * return value / length(value);
+ * }
+ *
+ * gridRes: (optional)
+ * The resolution of the mesh to generate. The default is a
+ * 1x1 grid but many vertex shaders need a higher resolution
+ * otherwise the only values passed in are the 4 corners
+ * which often have the same value.
+ *
+ * tests:
+ * The code for each test. It is assumed the tests are for
+ * float, vec2, vec3, vec4 in that order.
+ *
+ * tolerance: (optional)
+ * Allow some tolerance in the comparisons. The tolerance is applied to
+ * both vertex and fragment shaders. The default tolerance is 0, meaning
+ * the values have to be identical.
+ *
+ * fragmentTolerance: (optional)
+ * Specify a tolerance which only applies to fragment shaders. The
+ * fragment-only tolerance will override the shared tolerance for
+ * fragment shaders if both are specified. Fragment shaders usually
+ * use mediump float precision so they sometimes require higher tolerance
+ * than vertex shaders which use highp by default.
+ */
+ runFeatureTest: runFeatureTest,
+
+ /*
+ * Runs a bunch of GLSL tests using the passed in parameters
+ *
+ * The parameters are:
+ *
+ * tests:
+ * Array of tests. For each test the following parameters are expected
+ *
+ * name:
+ * some description of the test
+ * reference:
+ * parameters for the reference shader (see below)
+ * test:
+ * parameters for the test shader (see below)
+ *
+ * The parameter for the reference and test shaders are
+ *
+ * shader: the GLSL for the shader
+ * subs: any substitutions you wish to define for the shader.
+ *
+ * Each shader is created from a basic template that
+ * defines an input and an output. You can see the
+ * templates at the top of this file. The input and output
+ * change depending on whether or not we are generating
+ * a vertex or fragment shader.
+ *
+ * All this code function does is a bunch of string substitutions.
+ * A substitution is defined by $(name). If name is found in
+ * the 'subs' parameter it is replaced. 4 special names exist.
+ *
+ * 'input' the input to your GLSL. Always a vec4. All change
+ * from 0 to 1 over the quad to be drawn.
+ *
+ * 'output' the output color. Also a vec4
+ *
+ * 'emu' a place to insert extra stuff
+ * 'extra' a place to insert extra stuff.
+ *
+ * You can think of the templates like this
+ *
+ * $(extra)
+ * $(emu)
+ *
+ * void main() {
+ * // do math to calculate input
+ * ...
+ *
+ * $(shader)
+ * }
+ *
+ * Your shader first has any subs you provided applied as well
+ * as 'input' and 'output'
+ *
+ * It is then inserted into the template which is also provided
+ * with your subs.
+ *
+ * gridRes: (optional)
+ * The resolution of the mesh to generate. The default is a
+ * 1x1 grid but many vertex shaders need a higher resolution
+ * otherwise the only values passed in are the 4 corners
+ * which often have the same value.
+ *
+ * tolerance: (optional)
+ * Allow some tolerance in the comparisons. The tolerance is applied to
+ * both vertex and fragment shaders. The default tolerance is 0, meaning
+ * the values have to be identical.
+ *
+ * fragmentTolerance: (optional)
+ * Specify a tolerance which only applies to fragment shaders. The
+ * fragment-only tolerance will override the shared tolerance for
+ * fragment shaders if both are specified. Fragment shaders usually
+ * use mediump float precision so they sometimes require higher tolerance
+ * than vertex shaders which use highp.
+ */
+ runBasicTest: runBasicTest,
+
+ /**
+ * Runs a bunch of GLSL tests using the passed in parameters. The
+ * expected results are computed as a reference image in JavaScript
+ * instead of on the GPU. The parameters are:
+ *
+ * feature:
+ * the name of the function being tested (eg, sin, dot,
+ * normalize)
+ *
+ * testFunc:
+ * The prototype of function to be tested not including the
+ * return type.
+ *
+ * args:
+ * The arguments to the function
+ *
+ * gridRes: (optional)
+ * The resolution of the mesh to generate. The default is a
+ * 1x1 grid but many vertex shaders need a higher resolution
+ * otherwise the only values passed in are the 4 corners
+ * which often have the same value.
+ *
+ * tests:
+ * Array of tests. It is assumed the tests are for float, vec2,
+ * vec3, vec4 in that order. For each test the following
+ * parameters are expected:
+ *
+ * source: the GLSL source code for the tests
+ *
+ * generator: a JavaScript function taking four parameters
+ * which evaluates the same function as the GLSL source,
+ * returning its result as a newly allocated array.
+ *
+ * tolerance: (optional) a per-test tolerance.
+ *
+ * extra: (optional)
+ * Extra GLSL code inserted at the top of each test's shader.
+ *
+ * tolerance: (optional)
+ * Allow some tolerance in the comparisons. The tolerance is applied to
+ * both vertex and fragment shaders. The default tolerance is 0, meaning
+ * the values have to be identical.
+ *
+ * fragmentTolerance: (optional)
+ * Specify a tolerance which only applies to fragment shaders. The
+ * fragment-only tolerance will override the shared tolerance for
+ * fragment shaders if both are specified. Fragment shaders usually
+ * use mediump float precision so they sometimes require higher tolerance
+ * than vertex shaders which use highp.
+ */
+ runReferenceImageTest: runReferenceImageTest,
+
+ none: false
+};
+
+}());
+
diff --git a/dom/canvas/test/webgl-conf/checkout/js/js-test-post.js b/dom/canvas/test/webgl-conf/checkout/js/js-test-post.js
new file mode 100644
index 000000000..e2e2f6031
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/js-test-post.js
@@ -0,0 +1,29 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+shouldBeTrue("successfullyParsed");
+_addSpan('<br /><span class="pass">TEST COMPLETE</span>');
+if (_jsTestPreVerboseLogging) {
+ _bufferedLogToConsole('TEST COMPLETE');
+}
+notifyFinishedToHarness()
diff --git a/dom/canvas/test/webgl-conf/checkout/js/js-test-pre.js b/dom/canvas/test/webgl-conf/checkout/js/js-test-pre.js
new file mode 100644
index 000000000..df30a6fab
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/js-test-pre.js
@@ -0,0 +1,744 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+(function() {
+ var testHarnessInitialized = false;
+
+ var initNonKhronosFramework = function() {
+ if (testHarnessInitialized) {
+ return;
+ }
+ testHarnessInitialized = true;
+
+ /* -- plaform specific code -- */
+
+ // WebKit Specific code. Add your code here.
+ if (window.testRunner && !window.layoutTestController) {
+ window.layoutTestController = window.testRunner;
+ }
+
+ if (window.layoutTestController) {
+ window.layoutTestController.overridePreference("WebKitWebGLEnabled", "1");
+ window.layoutTestController.dumpAsText();
+ window.layoutTestController.waitUntilDone();
+ }
+ if (window.internals) {
+ // The WebKit testing system compares console output.
+ // Because the output of the WebGL Tests is GPU dependent
+ // we turn off console messages.
+ window.console.log = function() { };
+ window.console.error = function() { };
+ window.internals.settings.setWebGLErrorsToConsoleEnabled(false);
+
+ // RAF doesn't work in LayoutTests. Disable it so the tests will
+ // use setTimeout instead.
+ window.requestAnimationFrame = undefined;
+ window.webkitRequestAnimationFrame = undefined;
+ }
+
+ /* -- end platform specific code --*/
+ }
+
+ this.initTestingHarness = function() {
+ initNonKhronosFramework();
+ }
+}());
+
+var getUrlOptions = (function() {
+ var _urlOptionsParsed = false;
+ var _urlOptions = {};
+ return function() {
+ if (!_urlOptionsParsed) {
+ var s = window.location.href;
+ var q = s.indexOf("?");
+ var e = s.indexOf("#");
+ if (e < 0) {
+ e = s.length;
+ }
+ var query = s.substring(q + 1, e);
+ var pairs = query.split("&");
+ for (var ii = 0; ii < pairs.length; ++ii) {
+ var keyValue = pairs[ii].split("=");
+ var key = keyValue[0];
+ var value = decodeURIComponent(keyValue[1]);
+ _urlOptions[key] = value;
+ }
+ _urlOptionsParsed = true;
+ }
+
+ return _urlOptions;
+ }
+})();
+
+if (typeof quietMode == 'undefined') {
+ var quietMode = (function() {
+ var _quietModeChecked = false;
+ var _isQuiet = false;
+ return function() {
+ if (!_quietModeChecked) {
+ _isQuiet = (getUrlOptions().quiet == 1);
+ _quietModeChecked = true;
+ }
+ return _isQuiet;
+ }
+ })();
+}
+
+function nonKhronosFrameworkNotifyDone() {
+ // WebKit Specific code. Add your code here.
+ if (window.layoutTestController) {
+ window.layoutTestController.notifyDone();
+ }
+}
+
+function reportTestResultsToHarness(success, msg) {
+ if (window.parent.webglTestHarness) {
+ window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg);
+ }
+}
+
+function reportSkippedTestResultsToHarness(success, msg) {
+ if (window.parent.webglTestHarness) {
+ window.parent.webglTestHarness.reportResults(window.location.pathname, success, msg, true);
+ }
+}
+
+function notifyFinishedToHarness() {
+ if (window.parent.webglTestHarness) {
+ window.parent.webglTestHarness.notifyFinished(window.location.pathname);
+ }
+ if (window.nonKhronosFrameworkNotifyDone) {
+ window.nonKhronosFrameworkNotifyDone();
+ }
+}
+
+var _bufferedConsoleLogs = [];
+
+function _bufferedLogToConsole(msg)
+{
+ if (_bufferedConsoleLogs) {
+ _bufferedConsoleLogs.push(msg);
+ } else if (window.console) {
+ window.console.log(msg);
+ }
+}
+
+// Public entry point exposed to many other files.
+function bufferedLogToConsole(msg)
+{
+ _bufferedLogToConsole(msg);
+}
+
+// Called implicitly by testFailed().
+function _flushBufferedLogsToConsole()
+{
+ if (_bufferedConsoleLogs) {
+ if (window.console) {
+ for (var ii = 0; ii < _bufferedConsoleLogs.length; ++ii) {
+ window.console.log(_bufferedConsoleLogs[ii]);
+ }
+ }
+ _bufferedConsoleLogs = null;
+ }
+}
+
+var _jsTestPreVerboseLogging = false;
+
+function enableJSTestPreVerboseLogging()
+{
+ _jsTestPreVerboseLogging = true;
+}
+
+function description(msg)
+{
+ initTestingHarness();
+ if (msg === undefined) {
+ msg = document.title;
+ }
+ // For MSIE 6 compatibility
+ var span = document.createElement("span");
+ span.innerHTML = '<p>' + msg + '</p><p>On success, you will see a series of "<span class="pass">PASS</span>" messages, followed by "<span class="pass">TEST COMPLETE</span>".</p>';
+ var description = document.getElementById("description");
+ if (description.firstChild)
+ description.replaceChild(span, description.firstChild);
+ else
+ description.appendChild(span);
+ if (_jsTestPreVerboseLogging) {
+ _bufferedLogToConsole(msg);
+ }
+}
+
+function _addSpan(contents)
+{
+ var span = document.createElement("span");
+ document.getElementById("console").appendChild(span); // insert it first so XHTML knows the namespace
+ span.innerHTML = contents + '<br />';
+}
+
+function debug(msg)
+{
+ if (!quietMode())
+ _addSpan(msg);
+ if (_jsTestPreVerboseLogging) {
+ _bufferedLogToConsole(msg);
+ }
+}
+
+function escapeHTML(text)
+{
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;");
+}
+/**
+ * Defines the exception type for a test failure.
+ * @constructor
+ * @param {string} message The error message.
+ */
+var TestFailedException = function (message) {
+ this.message = message;
+ this.name = "TestFailedException";
+};
+
+/**
+ * @param {string=} msg
+ */
+function testPassed(msg) {
+ msg = msg || 'Passed';
+ if (_currentTestName)
+ msg = _currentTestName + ': ' + msg;
+
+ reportTestResultsToHarness(true, msg);
+
+ if (!quietMode())
+ _addSpan('<span><span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
+ if (_jsTestPreVerboseLogging) {
+ _bufferedLogToConsole('PASS ' + msg);
+ }
+}
+
+/**
+ * @param {string=} msg
+ */
+function testFailed(msg) {
+ msg = msg || 'Failed';
+ if (_currentTestName)
+ msg = _currentTestName + ': ' + msg;
+
+ reportTestResultsToHarness(false, msg);
+ _addSpan('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
+ _bufferedLogToConsole('FAIL ' + msg);
+ _flushBufferedLogsToConsole();
+}
+
+var _currentTestName;
+
+/**
+ * Sets the current test name for usage within testPassedOptions/testFailedOptions.
+ * @param {string=} name The name to set as the current test name.
+ */
+function setCurrentTestName(name)
+{
+ _currentTestName = name;
+}
+
+/**
+ * Gets the current test name in use within testPassedOptions/testFailedOptions.
+ * @return {string} The name of the current test.
+ */
+function getCurrentTestName()
+{
+ return _currentTestName;
+}
+
+/**
+ * Variation of the testPassed function, with the option to not show (and thus not count) the test's pass result.
+ * @param {string} msg The message to be shown in the pass result.
+ * @param {boolean} addSpan Indicates whether the message will be visible (thus counted in the results) or not.
+ */
+function testPassedOptions(msg, addSpan)
+{
+ if (addSpan && !quietMode())
+ {
+ reportTestResultsToHarness(true, _currentTestName + ": " + msg);
+ _addSpan('<span><span class="pass">PASS</span> ' + escapeHTML(_currentTestName) + ": " + escapeHTML(msg) + '</span>');
+ }
+ if (_jsTestPreVerboseLogging) {
+ _bufferedLogToConsole('PASS ' + msg);
+ }
+}
+
+/**
+ * Report skipped tests.
+ * @param {string} msg The message to be shown in the skip result.
+ * @param {boolean} addSpan Indicates whether the message will be visible (thus counted in the results) or not.
+ */
+function testSkippedOptions(msg, addSpan)
+{
+ if (addSpan && !quietMode())
+ {
+ reportSkippedTestResultsToHarness(true, _currentTestName + ": " + msg);
+ _addSpan('<span><span class="warn">SKIP</span> ' + escapeHTML(_currentTestName) + ": " + escapeHTML(msg) + '</span>');
+ }
+ if (_jsTestPreVerboseLogging) {
+ _bufferedLogToConsole('SKIP' + msg);
+ }
+}
+
+/**
+ * Variation of the testFailed function, with the option to throw an exception or not.
+ * @param {string} msg The message to be shown in the fail result.
+ * @param {boolean} exthrow Indicates whether the function will throw a TestFailedException or not.
+ */
+function testFailedOptions(msg, exthrow)
+{
+ reportTestResultsToHarness(false, _currentTestName + ": " + msg);
+ _addSpan('<span><span class="fail">FAIL</span> ' + escapeHTML(_currentTestName) + ": " + escapeHTML(msg) + '</span>');
+ _bufferedLogToConsole('FAIL ' + msg);
+ _flushBufferedLogsToConsole();
+ if (exthrow) {
+ _currentTestName = ""; //Remembering to set the name of current testcase to empty string.
+ throw new TestFailedException(msg);
+ }
+}
+
+function areArraysEqual(_a, _b)
+{
+ try {
+ if (_a.length !== _b.length)
+ return false;
+ for (var i = 0; i < _a.length; i++)
+ if (_a[i] !== _b[i])
+ return false;
+ } catch (ex) {
+ return false;
+ }
+ return true;
+}
+
+function isMinusZero(n)
+{
+ // the only way to tell 0 from -0 in JS is the fact that 1/-0 is
+ // -Infinity instead of Infinity
+ return n === 0 && 1/n < 0;
+}
+
+function isResultCorrect(_actual, _expected)
+{
+ if (_expected === 0)
+ return _actual === _expected && (1/_actual) === (1/_expected);
+ if (_actual === _expected)
+ return true;
+ if (typeof(_expected) == "number" && isNaN(_expected))
+ return typeof(_actual) == "number" && isNaN(_actual);
+ if (Object.prototype.toString.call(_expected) == Object.prototype.toString.call([]))
+ return areArraysEqual(_actual, _expected);
+ return false;
+}
+
+function stringify(v)
+{
+ if (v === 0 && 1/v < 0)
+ return "-0";
+ else return "" + v;
+}
+
+function evalAndLog(_a)
+{
+ if (typeof _a != "string")
+ debug("WARN: tryAndLog() expects a string argument");
+
+ // Log first in case things go horribly wrong or this causes a sync event.
+ debug(_a);
+
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ testFailed(_a + " threw exception " + e);
+ }
+ return _av;
+}
+
+function shouldBe(_a, _b, quiet)
+{
+ if (typeof _a != "string" || typeof _b != "string")
+ debug("WARN: shouldBe() expects string arguments");
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+
+ if (exception)
+ testFailed(_a + " should be " + _bv + ". Threw exception " + exception);
+ else if (isResultCorrect(_av, _bv)) {
+ if (!quiet) {
+ testPassed(_a + " is " + _b);
+ }
+ } else if (typeof(_av) == typeof(_bv))
+ testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
+ else
+ testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
+}
+
+function shouldNotBe(_a, _b, quiet)
+{
+ if (typeof _a != "string" || typeof _b != "string")
+ debug("WARN: shouldNotBe() expects string arguments");
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+
+ if (exception)
+ testFailed(_a + " should not be " + _bv + ". Threw exception " + exception);
+ else if (!isResultCorrect(_av, _bv)) {
+ if (!quiet) {
+ testPassed(_a + " is not " + _b);
+ }
+ } else
+ testFailed(_a + " should not be " + _bv + ".");
+}
+
+function shouldBeTrue(_a) { shouldBe(_a, "true"); }
+function shouldBeFalse(_a) { shouldBe(_a, "false"); }
+function shouldBeNaN(_a) { shouldBe(_a, "NaN"); }
+function shouldBeNull(_a) { shouldBe(_a, "null"); }
+
+function shouldBeEqualToString(a, b)
+{
+ var unevaledString = '"' + b.replace(/"/g, "\"") + '"';
+ shouldBe(a, unevaledString);
+}
+
+function shouldEvaluateTo(actual, expected) {
+ // A general-purpose comparator. 'actual' should be a string to be
+ // evaluated, as for shouldBe(). 'expected' may be any type and will be
+ // used without being eval'ed.
+ if (expected == null) {
+ // Do this before the object test, since null is of type 'object'.
+ shouldBeNull(actual);
+ } else if (typeof expected == "undefined") {
+ shouldBeUndefined(actual);
+ } else if (typeof expected == "function") {
+ // All this fuss is to avoid the string-arg warning from shouldBe().
+ try {
+ var actualValue = eval(actual);
+ } catch (e) {
+ testFailed("Evaluating " + actual + ": Threw exception " + e);
+ return;
+ }
+ shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'",
+ "'" + expected.toString().replace(/\n/g, "") + "'");
+ } else if (typeof expected == "object") {
+ shouldBeTrue(actual + " == '" + expected + "'");
+ } else if (typeof expected == "string") {
+ shouldBe(actual, expected);
+ } else if (typeof expected == "boolean") {
+ shouldBe("typeof " + actual, "'boolean'");
+ if (expected)
+ shouldBeTrue(actual);
+ else
+ shouldBeFalse(actual);
+ } else if (typeof expected == "number") {
+ shouldBe(actual, stringify(expected));
+ } else {
+ debug(expected + " is unknown type " + typeof expected);
+ shouldBeTrue(actual, "'" +expected.toString() + "'");
+ }
+}
+
+function shouldBeNonZero(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + " should be non-zero. Threw exception " + exception);
+ else if (_av != 0)
+ testPassed(_a + " is non-zero.");
+ else
+ testFailed(_a + " should be non-zero. Was " + _av);
+}
+
+function shouldBeNonNull(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + " should be non-null. Threw exception " + exception);
+ else if (_av != null)
+ testPassed(_a + " is non-null.");
+ else
+ testFailed(_a + " should be non-null. Was " + _av);
+}
+
+function shouldBeUndefined(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + " should be undefined. Threw exception " + exception);
+ else if (typeof _av == "undefined")
+ testPassed(_a + " is undefined.");
+ else
+ testFailed(_a + " should be undefined. Was " + _av);
+}
+
+function shouldBeDefined(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + " should be defined. Threw exception " + exception);
+ else if (_av !== undefined)
+ testPassed(_a + " is defined.");
+ else
+ testFailed(_a + " should be defined. Was " + _av);
+}
+
+function shouldBeLessThanOrEqual(_a, _b) {
+ if (typeof _a != "string" || typeof _b != "string")
+ debug("WARN: shouldBeLessThanOrEqual expects string arguments");
+
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+
+ if (exception)
+ testFailed(_a + " should be <= " + _b + ". Threw exception " + exception);
+ else if (typeof _av == "undefined" || _av > _bv)
+ testFailed(_a + " should be >= " + _b + ". Was " + _av + " (of type " + typeof _av + ").");
+ else
+ testPassed(_a + " is <= " + _b);
+}
+
+function shouldBeGreaterThanOrEqual(_a, _b) {
+ if (typeof _a != "string" || typeof _b != "string")
+ debug("WARN: shouldBeGreaterThanOrEqual expects string arguments");
+
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+
+ if (exception)
+ testFailed(_a + " should be >= " + _b + ". Threw exception " + exception);
+ else if (typeof _av == "undefined" || _av < _bv)
+ testFailed(_a + " should be >= " + _b + ". Was " + _av + " (of type " + typeof _av + ").");
+ else
+ testPassed(_a + " is >= " + _b);
+}
+
+function expectTrue(v, msg) {
+ if (v) {
+ testPassed(msg);
+ } else {
+ testFailed(msg);
+ }
+}
+
+function shouldThrow(_a, _e)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ var _ev;
+ if (_e)
+ _ev = eval(_e);
+
+ if (exception) {
+ if (typeof _e == "undefined" || exception == _ev)
+ testPassed(_a + " threw exception " + exception + ".");
+ else
+ testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + exception + ".");
+ } else if (typeof _av == "undefined")
+ testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined.");
+ else
+ testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
+}
+
+function shouldBeType(_a, _type) {
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ var _typev = eval(_type);
+
+ if(_typev === Number){
+ if(_av instanceof Number){
+ testPassed(_a + " is an instance of Number");
+ }
+ else if(typeof(_av) === 'number'){
+ testPassed(_a + " is an instance of Number");
+ }
+ else{
+ testFailed(_a + " is not an instance of Number");
+ }
+ }
+ else if (_av instanceof _typev) {
+ testPassed(_a + " is an instance of " + _type);
+ } else {
+ testFailed(_a + " is not an instance of " + _type);
+ }
+}
+
+/**
+ * Shows a message in case expression test fails.
+ * @param {boolean} exp
+ * @param {straing} message
+ */
+function checkMessage(exp, message) {
+ if ( !exp )
+ _addSpan('<span><span class="warn">WARNING</span> ' + escapeHTML(_currentTestName) + ": " + escapeHTML(message) + '</span>');
+}
+
+function assertMsg(assertion, msg) {
+ if (assertion) {
+ testPassed(msg);
+ } else {
+ testFailed(msg);
+ }
+}
+
+/**
+ * Variation of the assertMsg function, with the option to not show (and thus not count) the test's pass result,
+ * and throw or not a TestFailedException in case of failure.
+ * @param {boolean} assertion If this is true, means success, else failure.
+ * @param {?string} msg The message to be shown in the result.
+ * @param {boolean} verbose In case of success, determines if the test will show it's result and count in the results.
+ * @param {boolean} exthrow In case of failure, determines if the function will throw a TestFailedException.
+ */
+function assertMsgOptions(assertion, msg, verbose, exthrow) {
+ if (assertion) {
+ testPassedOptions(msg, verbose);
+ } else {
+ testFailedOptions(msg, exthrow);
+ }
+}
+
+
+function webglHarnessCollectGarbage() {
+ if (window.GCController) {
+ window.GCController.collect();
+ return;
+ }
+
+ if (window.opera && window.opera.collect) {
+ window.opera.collect();
+ return;
+ }
+
+ try {
+ window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindowUtils)
+ .garbageCollect();
+ return;
+ } catch(e) {}
+
+ if (window.gc) {
+ window.gc();
+ return;
+ }
+
+ if (window.CollectGarbage) {
+ CollectGarbage();
+ return;
+ }
+
+ function gcRec(n) {
+ if (n < 1)
+ return {};
+ var temp = {i: "ab" + i + (i / 100000)};
+ temp += "foo";
+ gcRec(n-1);
+ }
+ for (var i = 0; i < 1000; i++)
+ gcRec(10);
+}
+
+function finishTest() {
+ successfullyParsed = true;
+ var epilogue = document.createElement("script");
+ var basePath = "";
+ var expectedBase = "js-test-pre.js";
+ var scripts = document.getElementsByTagName('script');
+ for (var script, i = 0; script = scripts[i]; i++) {
+ var src = script.src;
+ var l = src.length;
+ if (src.substr(l - expectedBase.length) == expectedBase) {
+ basePath = src.substr(0, l - expectedBase.length);
+ break;
+ }
+ }
+ epilogue.src = basePath + "js-test-post.js";
+ document.body.appendChild(epilogue);
+}
+
diff --git a/dom/canvas/test/webgl-conf/checkout/js/pnglib.js b/dom/canvas/test/webgl-conf/checkout/js/pnglib.js
new file mode 100644
index 000000000..d2a9b99e0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/pnglib.js
@@ -0,0 +1,207 @@
+/**
+* A handy class to calculate color values.
+*
+* @version 1.0
+* @author Robert Eisele <robert@xarg.org>
+* @copyright Copyright (c) 2010, Robert Eisele
+* @link http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/
+* @license http://www.opensource.org/licenses/bsd-license.php BSD License
+*
+*/
+
+(function() {
+
+ // helper functions for that ctx
+ function write(buffer, offs) {
+ for (var i = 2; i < arguments.length; i++) {
+ for (var j = 0; j < arguments[i].length; j++) {
+ buffer[offs++] = arguments[i].charAt(j);
+ }
+ }
+ }
+
+ function byte2(w) {
+ return String.fromCharCode((w >> 8) & 255, w & 255);
+ }
+
+ function byte4(w) {
+ return String.fromCharCode((w >> 24) & 255, (w >> 16) & 255, (w >> 8) & 255, w & 255);
+ }
+
+ function byte2lsb(w) {
+ return String.fromCharCode(w & 255, (w >> 8) & 255);
+ }
+
+ window.PNGlib = function(width,height,depth) {
+
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+
+ // pixel data and row filter identifier size
+ this.pix_size = height * (width + 1);
+
+ // deflate header, pix_size, block headers, adler32 checksum
+ this.data_size = 2 + this.pix_size + 5 * Math.floor((0xfffe + this.pix_size) / 0xffff) + 4;
+
+ // offsets and sizes of Png chunks
+ this.ihdr_offs = 0; // IHDR offset and size
+ this.ihdr_size = 4 + 4 + 13 + 4;
+ this.plte_offs = this.ihdr_offs + this.ihdr_size; // PLTE offset and size
+ this.plte_size = 4 + 4 + 3 * depth + 4;
+ this.trns_offs = this.plte_offs + this.plte_size; // tRNS offset and size
+ this.trns_size = 4 + 4 + depth + 4;
+ this.idat_offs = this.trns_offs + this.trns_size; // IDAT offset and size
+ this.idat_size = 4 + 4 + this.data_size + 4;
+ this.iend_offs = this.idat_offs + this.idat_size; // IEND offset and size
+ this.iend_size = 4 + 4 + 4;
+ this.buffer_size = this.iend_offs + this.iend_size; // total PNG size
+
+ this.buffer = new Array();
+ this.palette = new Object();
+ this.pindex = 0;
+
+ var _crc32 = new Array();
+
+ // initialize buffer with zero bytes
+ for (var i = 0; i < this.buffer_size; i++) {
+ this.buffer[i] = "\x00";
+ }
+
+ // initialize non-zero elements
+ write(this.buffer, this.ihdr_offs, byte4(this.ihdr_size - 12), 'IHDR', byte4(width), byte4(height), "\x08\x03");
+ write(this.buffer, this.plte_offs, byte4(this.plte_size - 12), 'PLTE');
+ write(this.buffer, this.trns_offs, byte4(this.trns_size - 12), 'tRNS');
+ write(this.buffer, this.idat_offs, byte4(this.idat_size - 12), 'IDAT');
+ write(this.buffer, this.iend_offs, byte4(this.iend_size - 12), 'IEND');
+
+ // initialize deflate header
+ var header = ((8 + (7 << 4)) << 8) | (3 << 6);
+ header+= 31 - (header % 31);
+
+ write(this.buffer, this.idat_offs + 8, byte2(header));
+
+ // initialize deflate block headers
+ for (var i = 0; (i << 16) - 1 < this.pix_size; i++) {
+ var size, bits;
+ if (i + 0xffff < this.pix_size) {
+ size = 0xffff;
+ bits = "\x00";
+ } else {
+ size = this.pix_size - (i << 16) - i;
+ bits = "\x01";
+ }
+ write(this.buffer, this.idat_offs + 8 + 2 + (i << 16) + (i << 2), bits, byte2lsb(size), byte2lsb(~size));
+ }
+
+ /* Create crc32 lookup table */
+ for (var i = 0; i < 256; i++) {
+ var c = i;
+ for (var j = 0; j < 8; j++) {
+ if (c & 1) {
+ c = -306674912 ^ ((c >> 1) & 0x7fffffff);
+ } else {
+ c = (c >> 1) & 0x7fffffff;
+ }
+ }
+ _crc32[i] = c;
+ }
+
+ // compute the index into a png for a given pixel
+ this.index = function(x,y) {
+ var i = y * (this.width + 1) + x + 1;
+ var j = this.idat_offs + 8 + 2 + 5 * Math.floor((i / 0xffff) + 1) + i;
+ return j;
+ }
+
+ // convert a color and build up the palette
+ this.color = function(red, green, blue, alpha) {
+
+ alpha = alpha >= 0 ? alpha : 255;
+ var color = (((((alpha << 8) | red) << 8) | green) << 8) | blue;
+
+ if (typeof this.palette[color] == "undefined") {
+ if (this.pindex == this.depth) return "\x00";
+
+ var ndx = this.plte_offs + 8 + 3 * this.pindex;
+
+ this.buffer[ndx + 0] = String.fromCharCode(red);
+ this.buffer[ndx + 1] = String.fromCharCode(green);
+ this.buffer[ndx + 2] = String.fromCharCode(blue);
+ this.buffer[this.trns_offs+8+this.pindex] = String.fromCharCode(alpha);
+
+ this.palette[color] = String.fromCharCode(this.pindex++);
+ }
+ return this.palette[color];
+ }
+
+ // output a PNG string, Base64 encoded
+ this.getBase64 = function() {
+
+ var s = this.getDump();
+
+ var ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+ var c1, c2, c3, e1, e2, e3, e4;
+ var l = s.length;
+ var i = 0;
+ var r = "";
+
+ do {
+ c1 = s.charCodeAt(i);
+ e1 = c1 >> 2;
+ c2 = s.charCodeAt(i+1);
+ e2 = ((c1 & 3) << 4) | (c2 >> 4);
+ c3 = s.charCodeAt(i+2);
+ if (l < i+2) { e3 = 64; } else { e3 = ((c2 & 0xf) << 2) | (c3 >> 6); }
+ if (l < i+3) { e4 = 64; } else { e4 = c3 & 0x3f; }
+ r+= ch.charAt(e1) + ch.charAt(e2) + ch.charAt(e3) + ch.charAt(e4);
+ } while ((i+= 3) < l);
+ return r;
+ }
+
+ // output a PNG string
+ this.getDump = function() {
+
+ // compute adler32 of output pixels + row filter bytes
+ var BASE = 65521; /* largest prime smaller than 65536 */
+ var NMAX = 5552; /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+ var s1 = 1;
+ var s2 = 0;
+ var n = NMAX;
+
+ for (var y = 0; y < this.height; y++) {
+ for (var x = -1; x < this.width; x++) {
+ s1+= this.buffer[this.index(x, y)].charCodeAt(0);
+ s2+= s1;
+ if ((n-= 1) == 0) {
+ s1%= BASE;
+ s2%= BASE;
+ n = NMAX;
+ }
+ }
+ }
+ s1%= BASE;
+ s2%= BASE;
+ write(this.buffer, this.idat_offs + this.idat_size - 8, byte4((s2 << 16) | s1));
+
+ // compute crc32 of the PNG chunks
+ function crc32(png, offs, size) {
+ var crc = -1;
+ for (var i = 4; i < size-4; i += 1) {
+ crc = _crc32[(crc ^ png[offs+i].charCodeAt(0)) & 0xff] ^ ((crc >> 8) & 0x00ffffff);
+ }
+ write(png, offs+size-4, byte4(crc ^ -1));
+ }
+
+ crc32(this.buffer, this.ihdr_offs, this.ihdr_size);
+ crc32(this.buffer, this.plte_offs, this.plte_size);
+ crc32(this.buffer, this.trns_offs, this.trns_size);
+ crc32(this.buffer, this.idat_offs, this.idat_size);
+ crc32(this.buffer, this.iend_offs, this.iend_size);
+
+ // convert PNG to string
+ return "\211PNG\r\n\032\n"+this.buffer.join('');
+ }
+ }
+
+})();
diff --git a/dom/canvas/test/webgl-conf/checkout/js/test-eval.js b/dom/canvas/test/webgl-conf/checkout/js/test-eval.js
new file mode 100644
index 000000000..2d863239e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/test-eval.js
@@ -0,0 +1,32 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/**
+ * Calls eval.
+ *
+ * This is here so other modules can use "use strict":
+ */
+TestEval = function(str) {
+ return eval(str);
+};
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js b/dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js
new file mode 100644
index 000000000..fd86bf5fd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js
@@ -0,0 +1,109 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+'use strict';
+description("This test ensures clipping works with wide points whose centers are out of the viewport");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("testbed", undefined, contextVersion);
+
+var pointSize;
+
+function setupProgram() {
+ var vs = "attribute vec4 pos;" +
+ "uniform float pointSize; " +
+ "void main() {" +
+ " gl_PointSize = pointSize;" +
+ " gl_Position = pos;" +
+ "}";
+ var fs = "precision mediump float;" +
+ "void main() {" +
+ " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);" +
+ "}";
+ var program = wtu.setupProgram(gl, [vs, fs], ['pos']);
+ if (program) {
+ var loc = gl.getUniformLocation(program, 'pointSize');
+ gl.uniform1f(loc, pointSize);
+ gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors after setting up program");
+ }
+ return program;
+}
+
+function runOneTestCase(vertex) {
+ debug("");
+ debug("testing point at (" + vertex[0] + ", " + vertex[1] + ", " + vertex[2] + ")");
+ var data = new Float32Array(vertex);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, data);
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors after running one test case");
+}
+
+function runTests() {
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+
+ var range = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
+ if (range[1] < 2.0) {
+ testPassed("ALIASDED_POINT_SIZE_RANGE less than 2");
+ return;
+ }
+ pointSize = 2.0;
+
+ var data = new Float32Array(4);
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
+
+ var program = setupProgram();
+ if (!program) {
+ testFailed("fail to set up program");
+ return;
+ }
+
+ gl.disable(gl.BLEND);
+ gl.disable(gl.DITHER);
+ gl.disable(gl.DEPTH_TEST);
+
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+
+ var vertices = [
+ [ 0.99, 0.5, 0.0, 1.0 ],
+ [ 1.01, 0.5, 0.0, 1.0 ],
+ [ 0.5, 0.99, 0.0, 1.0 ],
+ [ 0.5, 1.01, 0.0, 1.0 ],
+ ];
+ for (var idx = 0; idx < vertices.length; ++idx) {
+ runOneTestCase(vertices[idx]);
+ }
+}
+
+runTests();
+debug("");
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js b/dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js
new file mode 100644
index 000000000..d824f3194
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js
@@ -0,0 +1,150 @@
+/*
+** Copyright (c) 2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+'use strict';
+
+// ESSL 1.00 spec section 5.8 (also ESSL 3.00 spec section 5.8):
+// "The l-value and the expression must satisfy the semantic requirements of both op and equals (=)"
+// In the semantic requirements of assignment (=):
+// "The lvalue-expression and rvalue-expression must have the same type"
+
+var runTest = function(contextVersion) {
+ var vertexTemplateESSL1 = [
+ 'precision mediump float;',
+
+ 'uniform $(rtype) ur;',
+ 'uniform $(ltype) ul;',
+
+ 'void main() {',
+ ' $(ltype) a = ul;',
+ ' a $(op) ur;',
+ ' gl_Position = vec4(float(a$(ltypeToScalar)));',
+ '}'
+ ].join('\n');
+
+ var vertexTemplateESSL3 = [
+ '#version 300 es',
+ vertexTemplateESSL1
+ ].join('\n');
+
+ var fragmentTemplateESSL1 = [
+ 'precision mediump float;',
+
+ 'uniform $(rtype) ur;',
+ 'uniform $(ltype) ul;',
+
+ 'void main() {',
+ ' $(ltype) a = ul;',
+ ' a $(op) ur;',
+ ' gl_FragColor = vec4(float(a$(ltypeToScalar)));',
+ '}'
+ ].join('\n');
+
+ var fragmentTemplateESSL3 = [
+ '#version 300 es',
+ 'out mediump vec4 my_FragColor;',
+ fragmentTemplateESSL1
+ ].join('\n').replace('gl_FragColor', 'my_FragColor');
+
+ var isNonSquareMatrix = function(typeStr) {
+ return typeStr.substring(0, 3) == 'mat' &&
+ typeStr.length > 5 &&
+ typeStr[3] != typeStr[5];
+ }
+
+ var vsTemplate = contextVersion < 2 ? vertexTemplateESSL1 : vertexTemplateESSL3;
+ var fsTemplate = contextVersion < 2 ? fragmentTemplateESSL1 : fragmentTemplateESSL3;
+
+ var wtu = WebGLTestUtils;
+
+ var tests = [];
+
+ var baseTypes = ['float', 'int'];
+ var vecTypes = [['vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4'], ['ivec2', 'ivec3', 'ivec4']];
+ if (contextVersion >= 2) {
+ vecTypes[0] = ['vec2', 'vec3', 'vec4', 'mat2x2', 'mat3x3', 'mat4x4', 'mat2x3', 'mat2x4', 'mat3x2', 'mat3x4', 'mat4x2', 'mat4x3'];
+ }
+ var ops = ['+=', '-=', '*=', '/='];
+
+ var fs, vs;
+ for (var k = 0; k < ops.length; ++k) {
+ var op = ops[k];
+ for (var i = 0; i < baseTypes.length; ++i) {
+ var baseType = baseTypes[i];
+ for (var j = 0; j < vecTypes[i].length; ++j) {
+ var vecType = vecTypes[i][j];
+ var vecTypeToScalar = vecType.substring(0, 3) == 'mat' ? '[0].x' : '.x';
+
+ var pushTest = function(ltype, rtype, ltypeToScalar, expectSuccess) {
+ vs = wtu.replaceParams(vsTemplate, {ltype: ltype, rtype: rtype, ltypeToScalar: ltypeToScalar, op: op});
+ fs = wtu.replaceParams(fsTemplate, {ltype: ltype, rtype: rtype, ltypeToScalar: ltypeToScalar, op: op});
+ tests.push({
+ vShaderSource: vs,
+ vShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: ltype + " " + op + " " + rtype + " in a vertex shader should " + (expectSuccess ? "succeed." : "fail.")
+ });
+ tests.push({
+ fShaderSource: fs,
+ fShaderSuccess: expectSuccess,
+ linkSuccess: expectSuccess,
+ passMsg: ltype + " " + op + " " + rtype + " in a fragment shader should " + (expectSuccess ? "succeed." : "fail.")
+ });
+ }
+
+ // "scalar op= vector" is not okay, since the result of op is a vector,
+ // which can't be assigned to a scalar.
+ pushTest(baseType, vecType, '', false);
+
+ if (j > 0) {
+ var vecType2 = vecTypes[i][j - 1];
+ // "vector1 op= vector2" is not okay when vector1 and vector2 have
+ // non-matching dimensions.
+ pushTest(vecType, vecType2, vecTypeToScalar, false);
+ }
+
+ // "vector op= scalar" is okay.
+ pushTest(vecType, baseType, vecTypeToScalar, true);
+
+ // vecX *= matX is okay (effectively, this treats vector as a row vector).
+ if (vecType.substring(0, 3) == 'vec' && op == '*=') {
+ pushTest(vecType, 'mat' + vecType[3], vecTypeToScalar, true);
+ }
+
+ if (op != '*=' || !isNonSquareMatrix(vecType)) {
+ // "vector1 op= vector2" is okay when vector1 and vector2 have the same
+ // type (does a component-wise operation or matrix multiplication).
+ pushTest(vecType, vecType, vecTypeToScalar, true);
+ } else {
+ // non-square matrices can only be compound multiplied with a square matrix.
+ pushTest(vecType, vecType, vecTypeToScalar, false);
+ pushTest(vecType, 'mat' + vecType[3], vecTypeToScalar, true);
+ }
+ }
+ }
+ }
+
+ GLSLConformanceTester.runTests(tests, contextVersion);
+}
+
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js
new file mode 100644
index 000000000..3a17f09b2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js
@@ -0,0 +1,140 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This test relies on the surrounding web page defining a variable
+// "contextVersion" which indicates what version of WebGL it's running
+// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc.
+
+"use strict";
+description("This test ensures various WebGL functions fail when passed invalid OpenGL ES enums.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", undefined, contextVersion);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking gl enums.");
+
+ var buffer = new ArrayBuffer(2);
+ var buf = new Uint16Array(buffer);
+ var tex = gl.createTexture();
+ var program = wtu.createProgram(gl, wtu.loadStandardVertexShader(gl), wtu.loadStandardFragmentShader(gl));
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var tests = [
+ "gl.disable(desktopGL['CLIP_PLANE0'])",
+ "gl.disable(desktopGL['POINT_SPRITE'])",
+ "gl.getBufferParameter(gl.ARRAY_BUFFER, desktopGL['PIXEL_PACK_BUFFER'])",
+ "gl.hint(desktopGL['PERSPECTIVE_CORRECTION_HINT'], gl.FASTEST)",
+ "gl.isEnabled(desktopGL['CLIP_PLANE0'])",
+ "gl.isEnabled(desktopGL['POINT_SPRITE'])",
+ "gl.pixelStorei(desktopGL['PACK_SWAP_BYTES'], 1)",
+ "gl.getParameter(desktopGL['NUM_COMPRESSED_TEXTURE_FORMATS'])",
+ "gl.getParameter(desktopGL['EXTENSIONS'])",
+ "gl.getParameter(desktopGL['SHADER_COMPILER'])",
+ "gl.getParameter(desktopGL['SHADER_BINARY_FORMATS'])",
+ "gl.getParameter(desktopGL['NUM_SHADER_BINARY_FORMATS'])",
+ ];
+
+ if (contextVersion < 2) {
+ tests = tests.concat([
+ "gl.blendEquation(desktopGL['MIN'])",
+ "gl.blendEquation(desktopGL['MAX'])",
+ "gl.blendEquationSeparate(desktopGL['MIN'], gl.FUNC_ADD)",
+ "gl.blendEquationSeparate(desktopGL['MAX'], gl.FUNC_ADD)",
+ "gl.blendEquationSeparate(gl.FUNC_ADD, desktopGL['MIN'])",
+ "gl.blendEquationSeparate(gl.FUNC_ADD, desktopGL['MAX'])",
+ "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['STREAM_READ'])",
+ "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['STREAM_COPY'])",
+ "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['STATIC_READ'])",
+ "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['STATIC_COPY'])",
+ "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['DYNAMIC_READ'])",
+ "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['DYNAMIC_COPY'])",
+ "gl.bindTexture(desktopGL['TEXTURE_2D_ARRAY'], tex)",
+ "gl.bindTexture(desktopGL['TEXTURE_3D'], tex)",
+ ]);
+ } else {
+ tests = tests.concat([
+ "gl.bindTexture(desktopGL['TEXTURE_RECTANGLE_EXT'], tex)",
+ "gl.enable(desktopGL['PRIMITIVE_RESTART_FIXED_INDEX'])",
+ "gl.getActiveUniforms(program, [0], desktopGL['UNIFORM_NAME_LENGTH'])",
+ "gl.getProgramParameter(program, desktopGL['ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH'])",
+ "gl.getProgramParameter(program, desktopGL['TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH'])",
+ "gl.getProgramParameter(program, desktopGL['PROGRAM_BINARY_RETRIEVABLE_HINT'])",
+ "gl.getProgramParameter(program, desktopGL['PROGRAM_BINARY_LENGTH'])",
+ "gl.getParameter(program, desktopGL['NUM_PROGRAM_BINARY_FORMATS'])",
+ ]);
+ }
+
+ for (var ii = 0; ii < tests.length; ++ii) {
+ TestEval(tests[ii]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, tests[ii] + " should return INVALID_ENUM.");
+ }
+
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ tests = [
+ "gl.getTexParameter(gl.TEXTURE_2D, desktopGL['GENERATE_MIPMAP'])",
+ "gl.texParameteri(gl.TEXTURE_2D, desktopGL['GENERATE_MIPMAP'], 1)",
+ "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, desktopGL['CLAMP_TO_BORDER'])",
+ ];
+
+ if (contextVersion < 2) {
+ tests = tests.concat([
+ "gl.texParameteri(desktopGL['TEXTURE_2D_ARRAY'], gl.TEXTURE_MAG_FILTER, gl.NEAREST)",
+ "gl.texParameteri(desktopGL['TEXTURE_3D'], gl.TEXTURE_MAG_FILTER, gl.NEAREST)",
+ ]);
+ } else {
+ tests = tests.concat([
+ "gl.texParameteri(desktopGL['TEXTURE_2D'], desktopGL['TEXTURE_SWIZZLE_R_EXT'], gl.RED)",
+ "gl.texParameteri(desktopGL['TEXTURE_2D'], desktopGL['TEXTURE_SWIZZLE_G_EXT'], gl.RED)",
+ "gl.texParameteri(desktopGL['TEXTURE_2D'], desktopGL['TEXTURE_SWIZZLE_B_EXT'], gl.RED)",
+ "gl.texParameteri(desktopGL['TEXTURE_2D'], desktopGL['TEXTURE_SWIZZLE_A_EXT'], gl.RED)",
+ "gl.texParameteri(desktopGL['TEXTURE_2D'], gl.TEXTURE_WRAP_R, desktopGL['CLAMP_TO_BORDER'])",
+ ]);
+ }
+
+ for (var ii = 0; ii < tests.length; ++ii) {
+ TestEval(tests[ii]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, tests[ii] + " should return INVALID_ENUM.");
+ }
+ if (contextVersion >= 2) {
+ var uniformBlockProgram = wtu.loadUniformBlockProgram(gl);
+ gl.linkProgram(uniformBlockProgram);
+ shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.LINK_STATUS)', 'true');
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+ gl.getActiveUniformBlockParameter(uniformBlockProgram, 0, desktopGL['UNIFORM_BLOCK_NAME_LENGTH']);
+ shouldBe('gl.getError()', 'gl.INVALID_ENUM');
+ }
+}
+
+debug("");
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js
new file mode 100644
index 000000000..db38fb05c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js
@@ -0,0 +1,200 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This test relies on the surrounding web page defining a variable
+// "contextVersion" which indicates what version of WebGL it's running
+// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc.
+
+"use strict";
+description();
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, contextVersion);
+
+// NOTE: We explicitly do this in a funky order
+// to hopefully find subtle bugs.
+
+var targets = [
+ 'TEXTURE_2D',
+ 'TEXTURE_2D',
+ 'TEXTURE_CUBE_MAP',
+ 'TEXTURE_CUBE_MAP'
+];
+
+if (contextVersion > 1) {
+ targets = targets.concat([
+ 'TEXTURE_2D_ARRAY',
+ 'TEXTURE_2D_ARRAY',
+ 'TEXTURE_3D',
+ 'TEXTURE_3D'
+ ]);
+}
+
+// Create textures on different active textures.
+for (var ii = 0; ii < targets.length; ++ii) {
+ var target = targets[ii];
+ var tex = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0 + ii);
+ gl.bindTexture(gl[target], tex);
+}
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+var states = [
+ { state: 'TEXTURE_WRAP_S', default: 'REPEAT', value1: 'CLAMP_TO_EDGE', value2: 'REPEAT' },
+ { state: 'TEXTURE_WRAP_T', default: 'REPEAT', value1: 'MIRRORED_REPEAT', value2: 'REPEAT' },
+ { state: 'TEXTURE_MAG_FILTER', default: 'LINEAR', value1: 'NEAREST', value2: 'LINEAR' },
+ { state: 'TEXTURE_MIN_FILTER', default: 'NEAREST_MIPMAP_LINEAR', value1: 'LINEAR_MIPMAP_LINEAR', value2: 'NEAREST' }
+];
+
+if (contextVersion > 1) {
+ states = states.concat([
+ { state: 'TEXTURE_WRAP_R', default: 'REPEAT', value1: 'CLAMP_TO_EDGE', value2: 'MIRRORED_REPEAT' },
+ { state: 'TEXTURE_COMPARE_FUNC', default: 'LEQUAL', value1: 'GREATER', value2: 'LESS' },
+ { state: 'TEXTURE_COMPARE_MODE', default: 'NONE', value1: 'COMPARE_REF_TO_TEXTURE', value2: 'NONE' },
+ { state: 'TEXTURE_BASE_LEVEL', default: 0, value1: 100, value2: 99 },
+ { state: 'TEXTURE_MAX_LEVEL', default: 1000, value1: 800, value2: 300 },
+ { state: 'TEXTURE_MIN_LOD', default: -1000.0, value1: -500.0, value2: -999.0 },
+ { state: 'TEXTURE_MAX_LOD', default: 1000.0, value1: 500.0, value2: 999.0 },
+ // Note: For TEXTURE_IMMUTABLE_LEVELS and TEXTURE_IMMUTABLE_FORMAT,
+ // these two pname are used by getTexParameter API only, not available in texParameter[fi] in specifications.
+ // Thus, these two states store default value only.
+ { state: 'TEXTURE_IMMUTABLE_LEVELS', default: 0, },
+ { state: 'TEXTURE_IMMUTABLE_FORMAT', default: false, }
+ ]);
+}
+
+function getStateInfoValue(stateInfo, item, method) {
+ switch (stateInfo.state) {
+ case 'TEXTURE_WRAP_R':
+ case 'TEXTURE_WRAP_S':
+ case 'TEXTURE_WRAP_T':
+ case 'TEXTURE_MAG_FILTER':
+ case 'TEXTURE_MIN_FILTER':
+ case 'TEXTURE_COMPARE_FUNC':
+ case 'TEXTURE_COMPARE_MODE':
+ if (method === 'Get') {
+ return 'gl["' + stateInfo[item] + '"]';
+ } else if (method === 'Set') {
+ return gl[stateInfo[item]];
+ }
+ break;
+ case 'TEXTURE_BASE_LEVEL':
+ case 'TEXTURE_MAX_LEVEL':
+ case 'TEXTURE_MIN_LOD':
+ case 'TEXTURE_MAX_LOD':
+ if (method === 'Get') {
+ return '' + stateInfo[item];
+ } else if (method === 'Set') {
+ return stateInfo[item];
+ }
+ break;
+ case 'TEXTURE_IMMUTABLE_LEVELS':
+ case 'TEXTURE_IMMUTABLE_FORMAT':
+ // Return default value only.
+ return '' + stateInfo.default;
+ default:
+ wtu.error("Not reached!");
+ return null;
+ break;
+ }
+}
+
+function applyStates(fn) {
+ for (var ss = 0; ss < states.length; ++ss) {
+ var stateInfo = states[ss];
+ for (var ii = 0; ii < targets.length; ++ii) {
+ var target = targets[ii];
+ gl.activeTexture(gl.TEXTURE0 + ii);
+ fn(target, stateInfo);
+ }
+ }
+}
+
+// test the default state.
+applyStates(function(target, stateInfo) {
+ var a = 'gl.getTexParameter(gl["' + target + '"], gl["' + stateInfo.state + '"])';
+ var b = getStateInfoValue(stateInfo, 'default', 'Get');
+ shouldBe(a, b);
+});
+
+// test new state
+applyStates(function(target, stateInfo) {
+ switch (stateInfo.state) {
+ case 'TEXTURE_IMMUTABLE_FORMAT':
+ case 'TEXTURE_IMMUTABLE_LEVELS':
+ // Skip these two pname for texParameterf[fi].
+ break;
+ case 'TEXTURE_MIN_LOD':
+ case 'TEXTURE_MAX_LOD':
+ gl.texParameterf(gl[target], gl[stateInfo.state], getStateInfoValue(stateInfo, 'value1', 'Set'));
+ break;
+ default:
+ gl.texParameteri(gl[target], gl[stateInfo.state], getStateInfoValue(stateInfo, 'value1', 'Set'));
+ break;
+ }
+});
+
+applyStates(function(target, stateInfo) {
+ var a = 'gl.getTexParameter(gl["' + target + '"], gl["' + stateInfo.state + '"])';
+ var b = getStateInfoValue(stateInfo, 'value1', 'Get');
+ shouldBe(a, b);
+});
+
+// test different states on each target.
+function getItem(count) {
+ return (count % 2) ? 'value2' : 'value1';
+}
+
+applyStates(function() {
+ var count = 0;
+ return function(target, stateInfo) {
+ switch (stateInfo.state) {
+ case 'TEXTURE_IMMUTABLE_FORMAT':
+ case 'TEXTURE_IMMUTABLE_LEVELS':
+ // Skip these two pname for texParameterf[fi].
+ break;
+ case 'TEXTURE_MIN_LOD':
+ case 'TEXTURE_MAX_LOD':
+ gl.texParameterf(gl[target], gl[stateInfo.state], getStateInfoValue(stateInfo, getItem(count), 'Set'));
+ break;
+ default:
+ gl.texParameteri(gl[target], gl[stateInfo.state], getStateInfoValue(stateInfo, getItem(count), 'Set'));
+ break;
+ }
+ ++count;
+ }
+}());
+
+applyStates(function() {
+ var count = 0;
+ return function(target, stateInfo) {
+ var a = 'gl.getTexParameter(gl["' + target + '"], gl["' + stateInfo.state + '"])';
+ var b = getStateInfoValue(stateInfo, getItem(count), 'Get');
+ shouldBe(a, b);
+ ++count;
+ };
+}());
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js
new file mode 100644
index 000000000..05e5a053d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js
@@ -0,0 +1,1092 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This test relies on the surrounding web page defining a variable
+// "contextVersion" which indicates what version of WebGL it's running
+// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc.
+
+"use strict";
+var wtu = WebGLTestUtils;
+description("Test of get calls against GL objects like getBufferParameter, etc.");
+
+var gl = wtu.create3DContext(undefined, undefined, contextVersion);
+
+function testInvalidArgument(funcName, argumentName, validArgumentArray, func) {
+ var validArguments = {};
+ for (var ii = 0; ii < validArgumentArray.length; ++ii) {
+ validArguments[validArgumentArray[ii]] = true;
+ }
+ var success = true;
+ for (var ii = 0; ii < 0x10000; ++ii) {
+ if (!validArguments[ii]) {
+ var result = func(ii);
+ if (result !== null) {
+ success = false;
+ testFailed(funcName + " returned " + result + " instead of null for invalid " + argumentName + " enum: " + wtu.glEnumToString(gl, ii));
+ break;
+ }
+ var err = gl.getError();
+ if (err != gl.INVALID_ENUM) {
+ success = false;
+ testFailed(funcName + " did not generate INVALID_ENUM for invalid " + argumentName + " enum: " + wtu.glEnumToString(gl, ii));
+ break;
+ }
+ }
+ }
+ if (success) {
+ testPassed(funcName + " correctly handled invalid " + argumentName + " enums");
+ }
+}
+
+debug("");
+debug("test getBufferParameter");
+// Test getBufferParameter
+var bufferTypes = [gl.ARRAY_BUFFER, gl.ELEMENT_ARRAY_BUFFER];
+if (contextVersion > 1) {
+ bufferTypes = bufferTypes.concat([gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, gl.PIXEL_PACK_BUFFER, gl.PIXEL_UNPACK_BUFFER, gl.TRANSFORM_FEEDBACK_BUFFER, gl.UNIFORM_BUFFER]);
+}
+for (var bb = 0; bb < bufferTypes.length; ++bb) {
+ var bufferType = bufferTypes[bb];
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(bufferType, buffer);
+ gl.bufferData(bufferType, 16, gl.DYNAMIC_DRAW);
+ var expression1 = "gl.getBufferParameter(gl." + wtu.glEnumToString(gl, bufferType) + ", gl.BUFFER_SIZE)";
+ var expression2 = "gl.getBufferParameter(gl." + wtu.glEnumToString(gl, bufferType) + ", gl.BUFFER_USAGE)";
+ shouldBe(expression1, '16');
+ shouldBe(expression2, 'gl.DYNAMIC_DRAW');
+ testInvalidArgument("getBufferParameter", "parameter", [gl.BUFFER_SIZE, gl.BUFFER_USAGE], function(bufferType) {
+ return function(parameter) {
+ return gl.getBufferParameter(bufferType, parameter);
+ };
+ }(bufferType));
+ gl.bindBuffer(bufferType, null);
+}
+testInvalidArgument(
+ "getBufferParameter",
+ "target",
+ bufferTypes,
+ function(target) {
+ return gl.getBufferParameter(target, gl.BUFFER_SIZE);
+ }
+);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+var testCases = [
+ { contextStencil: true},
+ { contextStencil: false}
+];
+
+for (var run = 0; run < testCases.length; ++run) {
+ debug("");
+ debug("Test getFramebufferAttachmentParameter with stencil " + testCases[run].contextStencil);
+
+ if (testCases[run].contextStencil) {
+ gl = wtu.create3DContext(null, {stencil: true}, contextVersion);
+ } else {
+ gl = wtu.create3DContext(null, {stencil: false}, contextVersion);
+ }
+
+ var texture = gl.createTexture();
+ var anotherTexture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array([
+ 0, 0, 0, 255,
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ 0, 0, 0, 255]));
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ var framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+ var colorAttachmentsNum = 1;
+ if (contextVersion > 1) {
+ gl.bindTexture(gl.TEXTURE_2D, anotherTexture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array([
+ 0, 0, 0, 255,
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ 0, 0, 0, 255]));
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ colorAttachmentsNum = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + colorAttachmentsNum - 1, gl.TEXTURE_2D, anotherTexture, 0);
+ }
+ var renderbuffer = gl.createRenderbuffer();
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ if (contextVersion == 1)
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 2, 2);
+ else
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, 2, 2);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
+ if (contextVersion > 1)
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ // The for loop tests two color attachments for WebGL 2: the first one (gl.COLOR_ATTACHMENT0)
+ // and the last one (gl.COLOR_ATTACHMENT0 + gl.MAX_COLOR_ATTACHMENTS - 1).
+ for (var ii = 0; ii < colorAttachmentsNum; ii += (colorAttachmentsNum > 1 ? colorAttachmentsNum - 1 : 1)) {
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.TEXTURE');
+ if (ii == 0)
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'texture');
+ else
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'anotherTexture');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL)', '0');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE)', '0');
+ if (contextVersion > 1) {
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_GREEN_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER)', '0');
+ }
+ }
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.RENDERBUFFER');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'renderbuffer');
+ if (contextVersion > 1) {
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.RENDERBUFFER');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'renderbuffer');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.RENDERBUFFER');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'renderbuffer');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)');
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)');
+ }
+ var validParametersForFBAttachment =
+ [ gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
+ gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+ gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
+ gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE
+ ];
+ if (contextVersion > 1) {
+ validParametersForFBAttachment = validParametersForFBAttachment.concat([
+ gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE,
+ gl.FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
+ gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
+ gl.FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
+ gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
+ gl.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
+ gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE,
+ gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING,
+ gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER
+ ]);
+ }
+ testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "parameter",
+ validParametersForFBAttachment,
+ function(parameter) {
+ return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT, parameter);
+ }
+ );
+ var validTargetsForFBAttachment = [gl.FRAMEBUFFER];
+ if (contextVersion > 1) {
+ validTargetsForFBAttachment = validTargetsForFBAttachment.concat([gl.READ_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER]);
+ }
+ testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "target",
+ validTargetsForFBAttachment,
+ function(target) {
+ return gl.getFramebufferAttachmentParameter(target, gl.COLOR_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ }
+ );
+ var validAttachmentsForFBAttachment = new Array(
+ gl.COLOR_ATTACHMENT0,
+ gl.DEPTH_ATTACHMENT,
+ gl.STENCIL_ATTACHMENT,
+ gl.DEPTH_STENCIL_ATTACHMENT
+ );
+ if (contextVersion > 1) {
+ for (var ii = 1; ii < gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); ++ii) {
+ validAttachmentsForFBAttachment[validAttachmentsForFBAttachment.length] = gl.COLOR_ATTACHMENT0 + ii;
+ }
+ }
+ testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "attachment",
+ validAttachmentsForFBAttachment,
+ function(attachment) {
+ return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ }
+ );
+ if (contextVersion > 1) {
+ // test default framebuffer
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.FRAMEBUFFER_DEFAULT');
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.FRAMEBUFFER_DEFAULT');
+ if (testCases[run].contextStencil)
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.FRAMEBUFFER_DEFAULT');
+ else
+ shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_GREEN_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)');
+ if (testCases[run].contextStencil) {
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)');
+ shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ } else {
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE)');
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)');
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)');
+ }
+ testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "parameter",
+ validParametersForFBAttachment,
+ function(parameter) {
+ return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, parameter);
+ }
+ );
+ testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "target",
+ validTargetsForFBAttachment,
+ function(target) {
+ return gl.getFramebufferAttachmentParameter(target, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ }
+ );
+ testInvalidArgument(
+ "getFramebufferAttachmentParameter",
+ "attachment",
+ [ gl.BACK,
+ gl.DEPTH,
+ gl.STENCIL
+ ],
+ function(attachment) {
+ return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ }
+ );
+ }
+}
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("test getAttachedShaders");
+var standardVert = wtu.loadStandardVertexShader(gl);
+var standardFrag = wtu.loadStandardFragmentShader(gl);
+var standardProgram = gl.createProgram();
+gl.attachShader(standardProgram, standardVert);
+gl.attachShader(standardProgram, standardFrag);
+gl.linkProgram(standardProgram);
+var shaders = gl.getAttachedShaders(standardProgram);
+shouldBe('shaders.length', '2');
+shouldBeTrue('shaders[0] == standardVert && shaders[1] == standardFrag || shaders[1] == standardVert && shaders[0] == standardFrag');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldThrow('gl.getAttachedShaders(null)');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldThrow('gl.getAttachedShaders(standardVert)');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Test getProgramParameter");
+shouldBe('gl.getProgramParameter(standardProgram, gl.DELETE_STATUS)', 'false');
+shouldBe('gl.getProgramParameter(standardProgram, gl.LINK_STATUS)', 'true');
+shouldBe('typeof gl.getProgramParameter(standardProgram, gl.VALIDATE_STATUS)', '"boolean"');
+shouldBe('gl.getProgramParameter(standardProgram, gl.ATTACHED_SHADERS)', '2');
+shouldBe('gl.getProgramParameter(standardProgram, gl.ACTIVE_ATTRIBUTES)', '2');
+shouldBe('gl.getProgramParameter(standardProgram, gl.ACTIVE_UNIFORMS)', '1');
+if (contextVersion > 1) {
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 1024, gl.DYNAMIC_DRAW);
+ var uniformBlockProgram = wtu.loadUniformBlockProgram(gl);
+ var transformFeedbackVars = ["normal", "ecPosition"];
+ gl.transformFeedbackVaryings(uniformBlockProgram, transformFeedbackVars, gl.INTERLEAVED_ATTRIBS);
+ gl.linkProgram(uniformBlockProgram);
+ shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.LINK_STATUS)', 'true');
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+ shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.ACTIVE_UNIFORM_BLOCKS)', '1');
+ shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.TRANSFORM_FEEDBACK_VARYINGS)', '2');
+ shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.TRANSFORM_FEEDBACK_BUFFER_MODE)', 'gl.INTERLEAVED_ATTRIBS');
+}
+var program = standardProgram;
+var validArrayForProgramParameter = [
+ gl.DELETE_STATUS,
+ gl.LINK_STATUS,
+ gl.VALIDATE_STATUS,
+ gl.ATTACHED_SHADERS,
+ gl.ACTIVE_ATTRIBUTES,
+ gl.ACTIVE_UNIFORMS
+];
+if (contextVersion > 1) {
+ validArrayForProgramParameter = validArrayForProgramParameter.concat([
+ gl.ACTIVE_UNIFORM_BLOCKS,
+ gl.TRANSFORM_FEEDBACK_VARYINGS,
+ gl.TRANSFORM_FEEDBACK_BUFFER_MODE
+ ]);
+ program = uniformBlockProgram;
+}
+testInvalidArgument(
+ "getProgramParameter",
+ "parameter",
+ validArrayForProgramParameter,
+ function(parameter) {
+ return gl.getProgramParameter(program, parameter);
+ }
+);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Test getRenderbufferParameter");
+shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)', '2');
+shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)', '2');
+// Note: we can't test the actual value of the internal format since
+// the implementation is allowed to change it.
+shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTERNAL_FORMAT)');
+shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE)');
+var colorbuffer = gl.createRenderbuffer();
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 2, 2);
+shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_RED_SIZE)');
+shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_GREEN_SIZE)');
+shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_BLUE_SIZE)');
+shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA_SIZE)');
+if (contextVersion > 1) {
+ gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA4, 2, 2);
+ shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)', '4');
+}
+var validArrayForRenderbuffer = new Array(
+ gl.RENDERBUFFER_WIDTH,
+ gl.RENDERBUFFER_HEIGHT,
+ gl.RENDERBUFFER_INTERNAL_FORMAT,
+ gl.RENDERBUFFER_RED_SIZE,
+ gl.RENDERBUFFER_GREEN_SIZE,
+ gl.RENDERBUFFER_BLUE_SIZE,
+ gl.RENDERBUFFER_ALPHA_SIZE,
+ gl.RENDERBUFFER_DEPTH_SIZE,
+ gl.RENDERBUFFER_STENCIL_SIZE
+);
+if (contextVersion > 1) {
+ validArrayForRenderbuffer[validArrayForRenderbuffer.length] = gl.RENDERBUFFER_SAMPLES;
+}
+testInvalidArgument(
+ "getRenderbufferParameter",
+ "parameter",
+ validArrayForRenderbuffer,
+ function(parameter) {
+ return gl.getRenderbufferParameter(gl.RENDERBUFFER, parameter);
+ });
+testInvalidArgument(
+ "getRenderbufferParameter",
+ "target",
+ [ gl.RENDERBUFFER ],
+ function(target) {
+ return gl.getRenderbufferParameter(target, gl.RENDERBUFFER_WIDTH);
+ }
+);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Test getShaderParameter");
+shouldBe('gl.getShaderParameter(standardVert, gl.SHADER_TYPE)', 'gl.VERTEX_SHADER');
+shouldBe('gl.getShaderParameter(standardVert, gl.DELETE_STATUS)', 'false');
+shouldBe('gl.getShaderParameter(standardVert, gl.COMPILE_STATUS)', 'true');
+testInvalidArgument(
+ "getShaderParameter",
+ "parameter",
+ [ gl.DELETE_STATUS,
+ gl.COMPILE_STATUS,
+ gl.SHADER_TYPE
+ ],
+ function(parameter) {
+ return gl.getShaderParameter(standardVert, parameter);
+ }
+);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Test getTexParameter");
+gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+gl.bindTexture(gl.TEXTURE_2D, texture);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER)', 'gl.NEAREST');
+shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER)', 'gl.NEAREST');
+shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)', 'gl.CLAMP_TO_EDGE');
+shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T)', 'gl.CLAMP_TO_EDGE');
+if (contextVersion > 1) {
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 0);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 10);
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAX_LOD, 10);
+ gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_LOD, 0);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL)', '0');
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC)', 'gl.LEQUAL');
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE)', 'gl.COMPARE_REF_TO_TEXTURE');
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL)', '10');
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MAX_LOD)', '10');
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MIN_LOD)', '0');
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R)', 'gl.CLAMP_TO_EDGE');
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_IMMUTABLE_FORMAT)', 'false');
+ shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_IMMUTABLE_LEVELS)', '0');
+}
+var validParametersForTexture = [
+ gl.TEXTURE_MAG_FILTER,
+ gl.TEXTURE_MIN_FILTER,
+ gl.TEXTURE_WRAP_S,
+ gl.TEXTURE_WRAP_T,
+];
+if (contextVersion > 1) {
+ validParametersForTexture = validParametersForTexture.concat([
+ gl.TEXTURE_BASE_LEVEL,
+ gl.TEXTURE_COMPARE_FUNC,
+ gl.TEXTURE_COMPARE_MODE,
+ gl.TEXTURE_MAX_LEVEL,
+ gl.TEXTURE_MAX_LOD,
+ gl.TEXTURE_MIN_LOD,
+ gl.TEXTURE_WRAP_R,
+ gl.TEXTURE_IMMUTABLE_FORMAT,
+ gl.TEXTURE_IMMUTABLE_LEVELS,
+ ]);
+}
+testInvalidArgument(
+ "getTexParameter",
+ "parameter",
+ validParametersForTexture,
+ function(parameter) {
+ return gl.getTexParameter(gl.TEXTURE_2D, parameter);
+ }
+);
+var validTargetsForTexture = [ gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP];
+if (contextVersion > 1) {
+ validTargetsForTexture = validTargetsForTexture.concat([ gl.TEXTURE_3D, gl.TEXTURE_2D_ARRAY]);
+}
+testInvalidArgument(
+ "getTexParameter",
+ "target",
+ validTargetsForTexture,
+ function(target) {
+ return gl.getTexParameter(target, gl.TEXTURE_MAG_FILTER);
+ }
+);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Test getUniform with all variants of data types");
+debug("Boolean uniform variables");
+var boolProgram = wtu.loadProgramFromFile(gl, "../../resources/boolUniformShader.vert", "../../resources/noopUniformShader.frag");
+shouldBe('gl.getProgramParameter(boolProgram, gl.LINK_STATUS)', 'true');
+var bvalLoc = gl.getUniformLocation(boolProgram, "bval");
+var bval2Loc = gl.getUniformLocation(boolProgram, "bval2");
+var bval3Loc = gl.getUniformLocation(boolProgram, "bval3");
+var bval4Loc = gl.getUniformLocation(boolProgram, "bval4");
+gl.useProgram(boolProgram);
+gl.uniform1i(bvalLoc, 1);
+gl.uniform2i(bval2Loc, 1, 0);
+gl.uniform3i(bval3Loc, 1, 0, 1);
+gl.uniform4i(bval4Loc, 1, 0, 1, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBe('gl.getUniform(boolProgram, bvalLoc)', 'true');
+shouldBe('gl.getUniform(boolProgram, bval2Loc)', '[true, false]');
+shouldBe('gl.getUniform(boolProgram, bval3Loc)', '[true, false, true]');
+shouldBe('gl.getUniform(boolProgram, bval4Loc)', '[true, false, true, false]');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("Integer uniform variables");
+var intProgram = wtu.loadProgramFromFile(gl, "../../resources/intUniformShader.vert", "../../resources/noopUniformShader.frag");
+shouldBe('gl.getProgramParameter(intProgram, gl.LINK_STATUS)', 'true');
+var ivalLoc = gl.getUniformLocation(intProgram, "ival");
+var ival2Loc = gl.getUniformLocation(intProgram, "ival2");
+var ival3Loc = gl.getUniformLocation(intProgram, "ival3");
+var ival4Loc = gl.getUniformLocation(intProgram, "ival4");
+gl.useProgram(intProgram);
+gl.uniform1i(ivalLoc, 1);
+gl.uniform2i(ival2Loc, 2, 3);
+gl.uniform3i(ival3Loc, 4, 5, 6);
+gl.uniform4i(ival4Loc, 7, 8, 9, 10);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBe('gl.getUniform(intProgram, ivalLoc)', '1');
+shouldBe('gl.getUniform(intProgram, ival2Loc)', '[2, 3]');
+shouldBe('gl.getUniform(intProgram, ival3Loc)', '[4, 5, 6]');
+shouldBe('gl.getUniform(intProgram, ival4Loc)', '[7, 8, 9, 10]');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("Float uniform variables");
+var floatProgram = wtu.loadProgramFromFile(gl, "../../resources/floatUniformShader.vert", "../../resources/noopUniformShader.frag");
+shouldBe('gl.getProgramParameter(floatProgram, gl.LINK_STATUS)', 'true');
+var fvalLoc = gl.getUniformLocation(floatProgram, "fval");
+var fval2Loc = gl.getUniformLocation(floatProgram, "fval2");
+var fval3Loc = gl.getUniformLocation(floatProgram, "fval3");
+var fval4Loc = gl.getUniformLocation(floatProgram, "fval4");
+gl.useProgram(floatProgram);
+gl.uniform1f(fvalLoc, 11);
+gl.uniform2f(fval2Loc, 12, 13);
+gl.uniform3f(fval3Loc, 14, 15, 16);
+gl.uniform4f(fval4Loc, 17, 18, 19, 20);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBe('gl.getUniform(floatProgram, fvalLoc)', '11');
+shouldBe('gl.getUniform(floatProgram, fval2Loc)', '[12, 13]');
+shouldBe('gl.getUniform(floatProgram, fval3Loc)', '[14, 15, 16]');
+shouldBe('gl.getUniform(floatProgram, fval4Loc)', '[17, 18, 19, 20]');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("Sampler uniform variables");
+var samplerProgram = wtu.loadProgramFromFile(gl, "../../resources/noopUniformShader.vert", "../../resources/samplerUniformShader.frag");
+shouldBe('gl.getProgramParameter(samplerProgram, gl.LINK_STATUS)', 'true');
+var s2DValLoc = gl.getUniformLocation(samplerProgram, "s2D");
+var sCubeValLoc = gl.getUniformLocation(samplerProgram, "sCube");
+gl.useProgram(samplerProgram);
+gl.uniform1i(s2DValLoc, 0);
+gl.uniform1i(sCubeValLoc, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBe('gl.getUniform(samplerProgram, s2DValLoc)', '0');
+shouldBe('gl.getUniform(samplerProgram, sCubeValLoc)', '1');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("Matrix uniform variables");
+var matProgram = wtu.loadProgramFromFile(gl, "../../resources/matUniformShader.vert", "../../resources/noopUniformShader.frag");
+shouldBe('gl.getProgramParameter(matProgram, gl.LINK_STATUS)', 'true');
+var mval2Loc = gl.getUniformLocation(matProgram, "mval2");
+var mval3Loc = gl.getUniformLocation(matProgram, "mval3");
+var mval4Loc = gl.getUniformLocation(matProgram, "mval4");
+gl.useProgram(matProgram);
+gl.uniformMatrix2fv(mval2Loc, false, [1, 2, 3, 4]);
+gl.uniformMatrix3fv(mval3Loc, false, [5, 6, 7, 8, 9, 10, 11, 12, 13]);
+gl.uniformMatrix4fv(mval4Loc, false, [14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBe('gl.getUniform(matProgram, mval2Loc)', '[1, 2, 3, 4]');
+shouldBe('gl.getUniform(matProgram, mval3Loc)', '[5, 6, 7, 8, 9, 10, 11, 12, 13]');
+shouldBe('gl.getUniform(matProgram, mval4Loc)', '[14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+if (contextVersion > 1) {
+ debug("Unsigned Integer uniform variables");
+ var uintProgram = wtu.loadProgramFromFile(gl, "../../resources/uintUniformShader.vert", "../../resources/noopUniformShaderES3.frag");
+ shouldBe('gl.getProgramParameter(uintProgram, gl.LINK_STATUS)', 'true');
+ var uvalLoc = gl.getUniformLocation(uintProgram, "uval");
+ var uval2Loc = gl.getUniformLocation(uintProgram, "uval2");
+ var uval3Loc = gl.getUniformLocation(uintProgram, "uval3");
+ var uval4Loc = gl.getUniformLocation(uintProgram, "uval4");
+ gl.useProgram(uintProgram);
+ gl.uniform1ui(uvalLoc, 1);
+ gl.uniform2ui(uval2Loc, 2, 3);
+ gl.uniform3ui(uval3Loc, 4, 5, 6);
+ gl.uniform4ui(uval4Loc, 7, 8, 9, 10);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBe('gl.getUniform(uintProgram, uvalLoc)', '1');
+ shouldBe('gl.getUniform(uintProgram, uval2Loc)', '[2, 3]');
+ shouldBe('gl.getUniform(uintProgram, uval3Loc)', '[4, 5, 6]');
+ shouldBe('gl.getUniform(uintProgram, uval4Loc)', '[7, 8, 9, 10]');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("Matrix uniform variables for WebGL 2");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ var matForWebGL2Program = wtu.loadProgramFromFile(gl, "../../resources/matForWebGL2UniformShader.vert", "../../resources/noopUniformShaderES3.frag");
+ shouldBe('gl.getProgramParameter(matForWebGL2Program, gl.LINK_STATUS)', 'true');
+ var mval2x3Loc = gl.getUniformLocation(matForWebGL2Program, "mval2x3");
+ var mval2x4Loc = gl.getUniformLocation(matForWebGL2Program, "mval2x4");
+ var mval3x2Loc = gl.getUniformLocation(matForWebGL2Program, "mval3x2");
+ var mval3x4Loc = gl.getUniformLocation(matForWebGL2Program, "mval3x4");
+ var mval4x2Loc = gl.getUniformLocation(matForWebGL2Program, "mval4x2");
+ var mval4x3Loc = gl.getUniformLocation(matForWebGL2Program, "mval4x3");
+ gl.useProgram(matForWebGL2Program);
+ gl.uniformMatrix2x3fv(mval2x3Loc, false, [1, 2, 3, 4, 5, 6]);
+ gl.uniformMatrix2x4fv(mval2x4Loc, false, [7, 8, 9, 10, 11, 12, 13, 14]);
+ gl.uniformMatrix3x2fv(mval3x2Loc, false, [15, 16, 17, 18, 19, 20]);
+ gl.uniformMatrix3x4fv(mval3x4Loc, false, [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
+ gl.uniformMatrix4x2fv(mval4x2Loc, false, [33, 34, 35, 36, 37, 38, 39, 40]);
+ gl.uniformMatrix4x3fv(mval4x3Loc, false, [41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBe('gl.getUniform(matForWebGL2Program, mval2x3Loc)', '[1, 2, 3, 4, 5, 6]');
+ shouldBe('gl.getUniform(matForWebGL2Program, mval2x4Loc)', '[7, 8, 9, 10, 11, 12, 13, 14]');
+ shouldBe('gl.getUniform(matForWebGL2Program, mval3x2Loc)', '[15, 16, 17, 18, 19, 20]');
+ shouldBe('gl.getUniform(matForWebGL2Program, mval3x4Loc)', '[21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]');
+ shouldBe('gl.getUniform(matForWebGL2Program, mval4x2Loc)', '[33, 34, 35, 36, 37, 38, 39, 40]');
+ shouldBe('gl.getUniform(matForWebGL2Program, mval4x3Loc)', '[41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52]');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("Sampler uniform variables for WebGL2");
+ var samplerForWebGL2Program = wtu.loadProgramFromFile(gl, "../../resources/noopUniformShaderES3.vert", "../../resources/samplerForWebGL2UniformShader.frag");
+ shouldBe('gl.getProgramParameter(samplerForWebGL2Program, gl.LINK_STATUS)', 'true');
+ var s3DValLoc = gl.getUniformLocation(samplerForWebGL2Program, "s3D");
+ var s2DArrayValLoc = gl.getUniformLocation(samplerForWebGL2Program, "s2DArray");
+ gl.useProgram(samplerForWebGL2Program);
+ gl.uniform1i(s3DValLoc, 0);
+ gl.uniform1i(s2DArrayValLoc, 1);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBe('gl.getUniform(samplerForWebGL2Program, s3DValLoc)', '0');
+ shouldBe('gl.getUniform(samplerForWebGL2Program, s2DArrayValLoc)', '1');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+}
+
+debug("");
+debug("test getVertexAttrib");
+var array = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+var buffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+gl.bufferData(gl.ARRAY_BUFFER, array, gl.DYNAMIC_DRAW);
+// Vertex attribute 0 is special in that it has no current state, so
+// fetching GL_CURRENT_VERTEX_ATTRIB generates an error. Use attribute
+// 1 for these tests instead.
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
+shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)', 'buffer');
+shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_ENABLED)', 'true');
+shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_SIZE)', '4');
+// Stride MUST be the value the user put in.
+shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_STRIDE)', '0');
+shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_TYPE)', 'gl.FLOAT');
+shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED)', 'false');
+if (contextVersion > 1) {
+ shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_DIVISOR)', '0');
+ shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_INTEGER)', 'false');
+ gl.vertexAttribDivisor(1, 2);
+ shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_DIVISOR)', '2');
+}
+gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 36, 12);
+shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_STRIDE)', '36');
+shouldBe('gl.getVertexAttribOffset(1, gl.VERTEX_ATTRIB_ARRAY_POINTER)', '12');
+gl.disableVertexAttribArray(1);
+shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_ENABLED)', 'false');
+gl.vertexAttrib4f(1, 5, 6, 7, 8);
+shouldBe('gl.getVertexAttrib(1, gl.CURRENT_VERTEX_ATTRIB)', '[5, 6, 7, 8]');
+if (contextVersion > 1) {
+ var intArray = new Int32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+ gl.bufferData(gl.ARRAY_BUFFER, intArray, gl.DYNAMIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ // feed fixed-point data to buffer
+ gl.vertexAttribIPointer(1, 4, gl.INT, false, 0, 0);
+ shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_TYPE)', 'gl.INT');
+ shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_INTEGER)', 'true');
+}
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+var validArrayForVertexAttrib = new Array(
+ gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
+ gl.VERTEX_ATTRIB_ARRAY_ENABLED,
+ gl.VERTEX_ATTRIB_ARRAY_SIZE,
+ gl.VERTEX_ATTRIB_ARRAY_STRIDE,
+ gl.VERTEX_ATTRIB_ARRAY_TYPE,
+ gl.VERTEX_ATTRIB_ARRAY_NORMALIZED,
+ gl.CURRENT_VERTEX_ATTRIB
+);
+if (contextVersion > 1) {
+ validArrayForVertexAttrib[validArrayForVertexAttrib.length] = gl.VERTEX_ATTRIB_ARRAY_DIVISOR;
+ validArrayForVertexAttrib[validArrayForVertexAttrib.length] = gl.VERTEX_ATTRIB_ARRAY_INTEGER;
+}
+testInvalidArgument(
+ "getVertexAttrib",
+ "parameter",
+ validArrayForVertexAttrib,
+ function(parameter) {
+ return gl.getVertexAttrib(1, parameter);
+ }
+);
+var numVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, 'gl.getVertexAttrib(' + numVertexAttribs + ', gl.CURRENT_VERTEX_ATTRIB)');
+
+debug("");
+debug("Test cases where name == 0");
+gl.deleteTexture(texture);
+shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
+gl.deleteRenderbuffer(renderbuffer);
+gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
+gl.deleteBuffer(buffer);
+shouldBeNull('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)');
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+if (contextVersion > 1) {
+ debug("");
+ debug("Test getInternalformatParameter")
+
+ shouldBeNonNull('gl.getInternalformatParameter(gl.RENDERBUFFER, gl.R32I, gl.SAMPLES)');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ testInvalidArgument(
+ "getInternalformatParameter",
+ "target",
+ [ gl.RENDERBUFFER ],
+ function(target) {
+ return gl.getInternalformatParameter(target, gl.R32I, gl.SAMPLES);
+ });
+
+ testInvalidArgument(
+ "getInternalformatParameter",
+ "pname",
+ [ gl.SAMPLES ],
+ function(pname) {
+ return gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA4, pname);
+ });
+
+ var validArrayForInterformat = new Array(
+ gl.R8, gl.R8_SNORM, gl.RG8, gl.RG8_SNORM,
+ gl.RGB8, gl.RGB8_SNORM, gl.RGB565, gl.RGBA4,
+ gl.RGB5_A1, gl.RGBA8, gl.RGBA8_SNORM, gl.RGB10_A2,
+ gl.RGB10_A2UI, gl.SRGB8, gl.SRGB8_ALPHA8, gl.R16F,
+ gl.RG16F, gl.RGB16F, gl.RGBA16F, gl.R32F,
+ gl.RG32F, gl.RGB32F, gl.RGBA32F, gl.R11F_G11F_B10F,
+ gl.RGB9_E5, gl.R8I, gl.R8UI, gl.R16I,
+ gl.R16UI, gl.R32I, gl.R32UI, gl.RG8I,
+ gl.RG8UI, gl.RG16I, gl.RG16UI, gl.RG32I,
+ gl.RG32UI, gl.RGB8I, gl.RGB8UI, gl.RGB16I,
+ gl.RGB16UI, gl.RGB32I, gl.RGB32UI, gl.RGBA8I,
+ gl.RGBA8UI, gl.RGBA16I, gl.RGBA16UI, gl.RGBA32I,
+ gl.RGBA32UI, gl.RGB, gl.RGBA, gl.DEPTH_STENCIL, gl.DEPTH_COMPONENT16,
+ gl.DEPTH_COMPONENT24, gl.DEPTH_COMPONENT32F, gl.DEPTH24_STENCIL8,
+ gl.DEPTH32F_STENCIL8, gl.STENCIL_INDEX8
+ );
+ testInvalidArgument(
+ "getInternalformatParameter",
+ "internalformat",
+ validArrayForInterformat,
+ function(internalformat) {
+ return gl.getInternalformatParameter(gl.RENDERBUFFER, internalformat, gl.SAMPLES);
+ });
+
+
+ debug("");
+ debug("Test getIndexedParameter");
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer);
+ gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 64, gl.DYNAMIC_DRAW);
+ gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 4, 8);
+ shouldBe('gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)', 'buffer');
+ shouldBe('gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)', '8');
+ shouldBe('gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)', '4');
+ var buffer1 = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, buffer1);
+ gl.bufferData(gl.UNIFORM_BUFFER, 64, gl.DYNAMIC_DRAW);
+ var offsetUniform = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, 1, buffer1, offsetUniform, 8);
+ shouldBe('gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)', 'buffer1');
+ shouldBe('gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)', '8');
+ shouldBe('gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)', 'offsetUniform');
+
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 1, null);
+ shouldBe('gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)', 'null');
+
+ var validArrayForTarget = new Array(
+ gl.TRANSFORM_FEEDBACK_BUFFER_BINDING,
+ gl.TRANSFORM_FEEDBACK_BUFFER_SIZE,
+ gl.TRANSFORM_FEEDBACK_BUFFER_START,
+ gl.UNIFORM_BUFFER_BINDING,
+ gl.UNIFORM_BUFFER_SIZE,
+ gl.UNIFORM_BUFFER_START
+ );
+ testInvalidArgument(
+ "getIndexedParameter",
+ "target",
+ validArrayForTarget,
+ function(target) {
+ return gl.getIndexedParameter(target, 0);
+ });
+
+ debug("");
+ debug("Test getSamplerParameter");
+ var sampler = gl.createSampler();
+ gl.samplerParameteri(sampler, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);
+ gl.samplerParameteri(sampler, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.samplerParameterf(sampler, gl.TEXTURE_MAX_LOD, 10);
+ gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.samplerParameterf(sampler, gl.TEXTURE_MIN_LOD, 0);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_COMPARE_FUNC)', 'gl.LEQUAL');
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_COMPARE_MODE)', 'gl.COMPARE_REF_TO_TEXTURE');
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_MAG_FILTER)', 'gl.NEAREST');
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_MAX_LOD)', '10');
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_MIN_FILTER)', 'gl.NEAREST');
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_MIN_LOD)', '0');
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_WRAP_R)', 'gl.CLAMP_TO_EDGE');
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_WRAP_S)', 'gl.CLAMP_TO_EDGE');
+ shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_WRAP_T)', 'gl.CLAMP_TO_EDGE');
+ var validArrayForSamplerParameter = new Array(
+ gl.TEXTURE_COMPARE_FUNC,
+ gl.TEXTURE_COMPARE_MODE,
+ gl.TEXTURE_MAG_FILTER,
+ gl.TEXTURE_MAX_LOD,
+ gl.TEXTURE_MIN_FILTER,
+ gl.TEXTURE_MIN_LOD,
+ gl.TEXTURE_WRAP_R,
+ gl.TEXTURE_WRAP_S,
+ gl.TEXTURE_WRAP_T
+ );
+ testInvalidArgument(
+ "getSamplerParameter",
+ "pname",
+ validArrayForSamplerParameter,
+ function(pname) {
+ return gl.getSamplerParameter(sampler, pname);
+ });
+
+ debug("");
+ debug("Test getSyncParameter");
+ var sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
+ shouldBe('gl.getSyncParameter(sync, gl.OBJECT_TYPE)', 'gl.SYNC_FENCE');
+ var sync_status = gl.getSyncParameter(sync, gl.SYNC_STATUS);
+ switch (sync_status) {
+ case gl.UNSIGNALED:
+ testPassed('gl.getSyncParameter(sync, gl.SYNC_CONDITION) is gl.UNSIGNALED');
+ break;
+ case gl.SIGNALED:
+ testPassed('gl.getSyncParameter(sync, gl.SYNC_CONDITION) is gl.SIGNALED');
+ break;
+ default:
+ testFailed('gl.getSyncParameter(sync, gl.SYNC_CONDITION) was ' + sync_status +
+ ', expected gl.UNSIGNALED or gl.SIGNALED');
+ break;
+ }
+ shouldBe('gl.getSyncParameter(sync, gl.SYNC_CONDITION)', 'gl.SYNC_GPU_COMMANDS_COMPLETE');
+ shouldBe('gl.getSyncParameter(sync, gl.SYNC_FLAGS)', '0');
+ var validArrayForSyncParameter = new Array(
+ gl.OBJECT_TYPE,
+ gl.SYNC_STATUS,
+ gl.SYNC_CONDITION,
+ gl.SYNC_FLAGS
+ );
+ testInvalidArgument(
+ "getSyncParameter",
+ "pname",
+ validArrayForSyncParameter,
+ function(pname) {
+ return gl.getSyncParameter(sync, pname);
+ });
+
+ debug("");
+ debug("Test getQueryParameter");
+ var query = gl.createQuery();
+ gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query);
+ gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ shouldBe('gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)', 'false');
+ // Queries' results are tested elsewhere in the conformance suite. It's complicated
+ // to wait for this query's result to become available and verify it.
+ var validArrayForPname = new Array(
+ gl.QUERY_RESULT,
+ gl.QUERY_RESULT_AVAILABLE
+ );
+ testInvalidArgument(
+ "getQueryParameter",
+ "pname",
+ validArrayForPname,
+ function(pname) {
+ return gl.getQueryParameter(query, pname);
+ }
+ );
+
+ debug("");
+ debug("Test getFragDataLocation");
+ var baseVertShader = '' +
+ '#version 300 es\n' +
+ 'uniform mat4 modelViewMatrix;\n' +
+ 'uniform mat4 projectionMatrix;\n' +
+ 'in vec4 vertex;\n' +
+ 'out vec4 position;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' position = modelViewMatrix * vertex;\n' +
+ ' gl_Position = projectionMatrix * position;\n' +
+ '}\n';
+ var baseFragShader = '' +
+ '#version 300 es\n' +
+ 'in lowp vec4 position;\n' +
+ 'layout(location = 0) out mediump vec4 fragColor;\n' +
+ 'void main (void)\n' +
+ '{\n' +
+ ' fragColor = position;\n' +
+ '}\n';
+ var vertShader = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vertShader, baseVertShader);
+ gl.compileShader(vertShader);
+ shouldBe('gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)', 'true');
+ var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fragShader, baseFragShader);
+ gl.compileShader(fragShader);
+ shouldBe('gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)', 'true');
+ var program = gl.createProgram();
+ gl.attachShader(program, vertShader);
+ gl.attachShader(program, fragShader);
+ gl.linkProgram(program);
+ shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)','true');
+ shouldBe('gl.getFragDataLocation(program, "vertexColor")', '-1');
+ shouldBe('gl.getFragDataLocation(program, "modelViewMatrix")', '-1');
+ shouldBe('gl.getFragDataLocation(program, "projectionMatrix")', '-1');
+ shouldBe('gl.getFragDataLocation(program, "position")', '-1');
+ shouldBe('gl.getFragDataLocation(program, "fragColor")', '0');
+
+ debug("");
+ debug("Test getActiveUniforms");
+ var program = wtu.loadUniformBlockProgram(gl);
+ gl.linkProgram(program);
+ shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ var numActiveUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+ var blockIndex = gl.getUniformBlockIndex(program, "Transform");
+ var uniformIndices = [];
+ for (var i = 0; i < numActiveUniforms; i++)
+ uniformIndices.push(i);
+ var types = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_TYPE);
+ var sizes = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_SIZE);
+ var blockIndices = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_BLOCK_INDEX);
+ var offsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET);
+ var arrayStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_ARRAY_STRIDE);
+ var matrixStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_MATRIX_STRIDE);
+ var rowMajors = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_IS_ROW_MAJOR);
+ for (var i = 0; i < numActiveUniforms; i++) {
+ if (types[i] != gl.FLOAT_MAT4 && types[i] != gl.FLOAT_MAT3)
+ testFailed("expected value: GL_FLOAT_MAT4 or GL_FLOAT_MAT3" + " actual value for UNIFORM_TYPE for uniform index[" + i + "]:" + wtu.glEnumToString(gl, types[i]));
+ if (sizes[i] != 1)
+ testFailed("expected value: 1" + " actual value for UNIFORM_SIZE for uniform index[" + i + "]:" + sizes[i]);
+ if (blockIndices[i] != blockIndex)
+ testFailed("expected value: 0" + " actual value for UNIFORM_BLOCK_INDEX for uniform index[" + i + "]:" + blockIndices[i]);
+ if (offsets[i] < 0)
+ testFailed("expected value >= 0" + " actual value for UNIFORM_OFFSET for uniform index[" + i + "]:" + offsets[i]);
+ if (arrayStrides[i] != 0)
+ testFailed("expected value: 0" + " actual value for UNIFORM_ARRAY_STRIDE for uniform index[" + i + "]:" + arrayStrides[i]);
+ if (matrixStrides[i] < 0)
+ testFailed("expected value >= 0" + " actual value for UNIFORM_MATRIX_STRIDE for uniform index[" + i + "]:" + matrixStrides[i]);
+ shouldBe('typeof rowMajors[i]', '"boolean"');
+ if (rowMajors[i] != false)
+ testFailed("expected value: 0" + " actual value for UNIFORM_IS_ROW_MAJOR for uniform index[" + i + "]:" + rowMajors[i]);
+ }
+
+ var validArrayForPname = new Array(
+ gl.UNIFORM_TYPE,
+ gl.UNIFORM_SIZE,
+ gl.UNIFORM_BLOCK_INDEX,
+ gl.UNIFORM_OFFSET,
+ gl.UNIFORM_ARRAY_STRIDE,
+ gl.UNIFORM_MATRIX_STRIDE,
+ gl.UNIFORM_IS_ROW_MAJOR
+ );
+ testInvalidArgument(
+ "getActiveUniforms",
+ "pname",
+ validArrayForPname,
+ function(pname) {
+ return gl.getActiveUniforms(program, uniformIndices, pname);
+ }
+ );
+
+ debug("");
+ debug("Test getUniformBlockIndex");
+ var program = wtu.loadUniformBlockProgram(gl);
+ gl.linkProgram(program);
+ shouldBeTrue('gl.getProgramParameter(program, gl.LINK_STATUS)');
+ shouldBe('gl.getUniformBlockIndex(program, "Transform")', '0');
+ shouldBe('gl.getUniformBlockIndex(program, "u_modelViewMatrix")', 'gl.INVALID_INDEX');
+ shouldBe('gl.getUniformBlockIndex(program, "normal")', 'gl.INVALID_INDEX');
+ shouldBe('gl.getUniformBlockIndex(program, "u_normal")', 'gl.INVALID_INDEX');
+ var noUniformProgram = wtu.loadStandardProgram(gl);
+ gl.linkProgram(noUniformProgram);
+ shouldBeTrue('gl.getProgramParameter(noUniformProgram, gl.LINK_STATUS)');
+ shouldBe('gl.getUniformBlockIndex(noUniformProgram, "u_modelViewProjMatrix")', 'gl.INVALID_INDEX');
+ shouldBe('gl.getUniformBlockIndex(noUniformProgram, "u_normal")', 'gl.INVALID_INDEX');
+
+ debug("");
+ debug("Test getActiveUniformBlockName");
+ var program = wtu.loadUniformBlockProgram(gl);
+ gl.linkProgram(program);
+ shouldBeTrue('gl.getProgramParameter(program, gl.LINK_STATUS)');
+ shouldBeEqualToString('gl.getActiveUniformBlockName(program, 0)', 'Transform');
+ shouldBeNull('gl.getActiveUniformBlockName(program, -1)');
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ shouldBeNull('gl.getActiveUniformBlockName(program, 1)');
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ shouldBeNull('gl.getActiveUniformBlockName(program, gl.INVALID_INDEX)');
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ var noLinkProgram = gl.createProgram();
+ shouldBeFalse('gl.getProgramParameter(noLinkProgram, gl.LINK_STATUS)');
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getActiveUniformBlockName(noLinkProgram, 0)');
+ var noUniformProgram = wtu.loadStandardProgram(gl);
+ gl.linkProgram(noUniformProgram);
+ shouldBeTrue('gl.getProgramParameter(noUniformProgram, gl.LINK_STATUS)');
+ shouldBeNull('gl.getActiveUniformBlockName(noUniformProgram, -1)');
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ shouldBeNull('gl.getActiveUniformBlockName(noUniformProgram, 0)');
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ shouldBeNull('gl.getActiveUniformBlockName(noUniformProgram, gl.INVALID_INDEX)');
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ debug("");
+ debug("Test getActiveUniformBlockParameter");
+ var program = wtu.loadUniformBlockProgram(gl);
+ gl.linkProgram(program);
+ shouldBeTrue('gl.getProgramParameter(program, gl.LINK_STATUS)');
+ shouldBe('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_BINDING)', '0');
+ gl.uniformBlockBinding(program, 0, 1);
+ shouldBe('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_BINDING)', '1');
+ // The actual block data size can be bigger than 164, depending on the uniform block layout.
+ shouldBeTrue('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_DATA_SIZE) >= 164');
+ shouldBe('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS)', '3');
+ shouldBeTrue('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER)');
+ shouldBeFalse('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER)');
+ var indices = gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES);
+ for (var i = 0; i < 3; i++) {
+ if (indices[i] < 0)
+ testFailed("expected value >= 0" + " actual value for UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES for uniform index[" + i + "]:" + indices[i]);
+ }
+ var validArrayForPname = new Array(
+ gl.UNIFORM_BLOCK_BINDING,
+ gl.UNIFORM_BLOCK_DATA_SIZE,
+ gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS,
+ gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
+ gl.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
+ gl.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
+ );
+ testInvalidArgument(
+ "getActiveUniformBlockParameter",
+ "pname",
+ validArrayForPname,
+ function(pname) {
+ return gl.getActiveUniformBlockParameter(program, 0, pname);
+ }
+ );
+}
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js
new file mode 100644
index 000000000..ddff0e550
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js
@@ -0,0 +1,280 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This test relies on the surrounding web page defining a variable
+// "contextVersion" which indicates what version of WebGL it's running
+// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc.
+
+"use strict";
+description("This test ensures WebGL implementations vertexAttrib can be set and read.");
+
+debug("");
+debug("Canvas.getContext");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", undefined, contextVersion);
+if (!gl) {
+ testFailed("context does not exist");
+} else {
+ testPassed("context exists");
+
+ debug("");
+ debug("Checking gl.vertexAttrib.");
+
+ var numVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+ for (var ii = 0; ii < numVertexAttribs; ++ii) {
+ gl.vertexAttrib1fv(ii, [1]);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib1fv(ii, new Float32Array([-1]));
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '-1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib2fv(ii, [1, 2]);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib2fv(ii, new Float32Array([1, -2]));
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '-2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib3fv(ii, [1, 2, 3]);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '3');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib3fv(ii, new Float32Array([1, -2, 3]));
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '-2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '3');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib4fv(ii, [1, 2, 3, 4]);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '3');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '4');
+
+ gl.vertexAttrib4fv(ii, new Float32Array([1, 2, -3, 4]));
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '-3');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '4');
+
+ gl.vertexAttrib1f(ii, 5);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '5');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib2f(ii, 6, 7);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '6');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '7');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib3f(ii, 7, 8, 9);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '7');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '8');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '9');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1');
+
+ gl.vertexAttrib4f(ii, 6, 7, 8, 9);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '6');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '7');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '8');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '9');
+
+ if (contextVersion > 1) {
+ gl.vertexAttribI4i(ii, -1, 0, 1, 2);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Int32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '-1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '2');
+
+ gl.vertexAttribI4ui(ii, 0, 1, 2, 3);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Uint32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '3');
+
+ gl.vertexAttribI4iv(ii, [-1, 0, 1, 2]);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Int32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '-1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '2');
+
+ gl.vertexAttribI4iv(ii, new Int32Array([1, 0, -1, 2]));
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Int32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '-1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '2');
+
+ gl.vertexAttribI4uiv(ii, [0, 1, 2, 3]);
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Uint32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '3');
+
+ gl.vertexAttribI4uiv(ii, new Uint32Array([0, 2, 1, 3]));
+ shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Uint32Array');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '0');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '1');
+ shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '3');
+ }
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ debug("");
+ debug("Checking out-of-range vertexAttrib index");
+ gl.getVertexAttrib(numVertexAttribs, gl.CURRENT_VERTEX_ATTRIB);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib1fv(numVertexAttribs, [1]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib1fv(numVertexAttribs, new Float32Array([-1]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib2fv(numVertexAttribs, [1, 2]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib2fv(numVertexAttribs, new Float32Array([1, -2]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib3fv(numVertexAttribs, [1, 2, 3]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib3fv(numVertexAttribs, new Float32Array([1, -2, 3]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib4fv(numVertexAttribs, [1, 2, 3, 4]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib4fv(numVertexAttribs, new Float32Array([1, 2, -3, 4]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib1f(numVertexAttribs, 5);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib2f(numVertexAttribs, 6, 7);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib3f(numVertexAttribs, 7, 8, 9);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib4f(numVertexAttribs, 6, 7, 8, 9);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ if (contextVersion > 1) {
+ gl.vertexAttribI4i(numVertexAttribs, -1, 0, 1, 2);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttribI4ui(numVertexAttribs, 0, 1, 2, 3);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttribI4iv(numVertexAttribs, [-1, 0, 1, 2]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttribI4iv(numVertexAttribs, new Int32Array([1, 0, -1, 2]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttribI4uiv(numVertexAttribs, [0, 1, 2, 3]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttribI4uiv(numVertexAttribs, new Uint32Array([0, 2, 1, 3]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ }
+
+ debug("");
+ debug("Checking invalid array lengths");
+ numVertexAttribs = numVertexAttribs - 1;
+ gl.vertexAttrib1fv(numVertexAttribs, []);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib1fv(numVertexAttribs, new Float32Array([]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib2fv(numVertexAttribs, [1]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib2fv(numVertexAttribs, new Float32Array([1]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib3fv(numVertexAttribs, [1, 2]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib3fv(numVertexAttribs, new Float32Array([1, -2]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib4fv(numVertexAttribs, [1, 2, 3]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttrib4fv(numVertexAttribs, new Float32Array([1, 2, -3]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ if (contextVersion > 1) {
+ gl.vertexAttribI4iv(numVertexAttribs, [-1, 0, 1]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttribI4iv(numVertexAttribs, new Int32Array([1, 0, -1]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttribI4uiv(numVertexAttribs, [0, 1, 2]);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+ gl.vertexAttribI4uiv(numVertexAttribs, new Uint32Array([0, 2, 1]));
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
+ }
+}
+
+debug("");
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js b/dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js
new file mode 100644
index 000000000..bd1ca2af8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js
@@ -0,0 +1,122 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This test relies on the surrounding web page defining a variable
+// "contextVersion" which indicates what version of WebGL it's running
+// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc.
+
+"use strict";
+var wtu = WebGLTestUtils;
+description(document.title);
+debug("Tests that instanceof works on WebGL objects.");
+debug("");
+
+function checkGLError(message) {
+ var error = gl.getError();
+ if (error != gl.NO_ERROR) {
+ wtu.error("Error: " + message + " caused " + wtu.glEnumToString(gl, error));
+ }
+}
+
+var gl = wtu.create3DContext("canvas", undefined, contextVersion);
+if (contextVersion === 1) {
+ shouldBeTrue('gl instanceof WebGLRenderingContext');
+} else if (contextVersion === 2) {
+ shouldBeTrue('gl instanceof WebGL2RenderingContext');
+}
+
+shouldBeTrue('gl.createBuffer() instanceof WebGLBuffer');
+checkGLError("createBuffer")
+
+shouldBeTrue('gl.createFramebuffer() instanceof WebGLFramebuffer');
+checkGLError("createFramebuffer")
+
+shouldBeTrue('gl.createProgram() instanceof WebGLProgram');
+checkGLError("createProgram")
+
+shouldBeTrue('gl.createRenderbuffer() instanceof WebGLRenderbuffer');
+checkGLError("createRenderbuffer")
+
+shouldBeTrue('gl.createShader(gl.VERTEX_SHADER) instanceof WebGLShader');
+checkGLError("createShader")
+
+shouldBeTrue('gl.createTexture() instanceof WebGLTexture');
+checkGLError("createTexture")
+
+if (contextVersion > 1) {
+ shouldBeTrue('gl.createQuery() instanceof WebGLQuery');
+ checkGLError("createQuery")
+
+ shouldBeTrue('gl.createSampler() instanceof WebGLSampler');
+ checkGLError("createSampler")
+
+ shouldBeTrue('gl.createTransformFeedback() instanceof WebGLTransformFeedback');
+ checkGLError("createTransformFeedback")
+
+ shouldBeTrue('gl.createVertexArray() instanceof WebGLVertexArrayObject');
+ checkGLError("createVertexArray")
+}
+
+var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['vPosition'], [0]);
+
+shouldBeTrue('gl.getUniformLocation(program, "color") instanceof WebGLUniformLocation');
+checkGLError("getUniformLocation")
+
+shouldBeTrue('gl.getActiveAttrib(program, 0) instanceof WebGLActiveInfo');
+checkGLError("getActiveAttrib")
+
+shouldBeTrue('gl.getActiveUniform(program, 0) instanceof WebGLActiveInfo');
+checkGLError("getActiveUniform")
+
+debug("");
+debug("Tests that those WebGL objects can not be constructed through new operator");
+debug("");
+
+function shouldThrowWithNew(objectType, objectName) {
+ try {
+ new objectType;
+ testFailed('new ' + objectName + ' did not throw');
+ } catch (e) {
+ testPassed('new ' + objectName + ' threw an error');
+ }
+}
+
+shouldThrowWithNew(window.WebGLRenderingContext, 'WebGLRenderingContext');
+shouldThrowWithNew(window.WebGLActiveInfo, 'WebGLActiveInfo');
+shouldThrowWithNew(window.WebGLBuffer, 'WebGLBuffer');
+shouldThrowWithNew(window.WebGLFramebuffer, 'WebGLFramebuffer');
+shouldThrowWithNew(window.WebGLProgram, 'WebGLProgram');
+shouldThrowWithNew(window.WebGLRenderbuffer, 'WebGLRenderbuffer');
+shouldThrowWithNew(window.WebGLShader, 'WebGLShader');
+shouldThrowWithNew(window.WebGLTexture, 'WebGLTexture');
+shouldThrowWithNew(window.WebGLUniformLocation, 'WebGLUniformLocation');
+shouldThrowWithNew(window.WebGLShaderPrecisionFormat, 'WebGLShaderPrecisionFormat');
+if (contextVersion > 1) {
+ shouldThrowWithNew(window.WebGLQuery, 'WebGLQuery');
+ shouldThrowWithNew(window.WebGLSampler, 'WebGLSampler');
+ shouldThrowWithNew(window.WebGLSync, 'WebGLSync');
+ shouldThrowWithNew(window.WebGLTransformFeedback, 'WebGLTransformFeedback');
+ shouldThrowWithNew(window.WebGLVertexArrayObject, 'WebGLVertexArrayObject');
+}
+
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js b/dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js
new file mode 100644
index 000000000..31abe5011
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js
@@ -0,0 +1,173 @@
+/*
+** Copyright (c) 2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+IterableTest = (function() {
+
+ var wtu = WebGLTestUtils;
+
+ function run(test, iterations) {
+ var target = iterations || 10;
+ var count = 0;
+
+ function doNextTest() {
+ ++count;
+ debug("Test " + count + " of " + target);
+ var success = test();
+ if (count < target && success !== false) {
+ wtu.waitForComposite(doNextTest);
+ //setTimeout(doNextTest, 100);
+ } else {
+ finishTest();
+ }
+ }
+
+ doNextTest();
+ }
+
+ // Creates a canvas and a texture then exits. There are
+ // no references to either so both should be garbage collected.
+ function createContextCreationAndDestructionTest() {
+ var textureSize = null;
+
+ return function() {
+ var canvas = document.createElement("canvas");
+ // This is safe for any device. See drawingBufferWidth in spec.
+ canvas.width = 2048;
+ canvas.height = 2048;
+ var gl = wtu.create3DContext(canvas);
+ if (textureSize === null) {
+ var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+ textureSize = Math.min(1024, maxTextureSize);
+ }
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize, textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ null);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+ return true;
+ };
+ }
+
+ // Creates many small canvases and attaches them to the DOM.
+ // This tests an edge case discovered in Chrome where the creation of multiple
+ // WebGL contexts would eventually lead to context creation failure.
+ // (crbug.com/319265) The test does not require that old contexts remain
+ // valid, only that new ones can be created.
+ function createContextCreationTest() {
+ return function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 1;
+ canvas.height = 1;
+
+ document.body.appendChild(canvas);
+
+ var gl = wtu.create3DContext(canvas);
+ if (!gl) {
+ return false;
+ }
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+ return true;
+ };
+ }
+
+ // Draws rectangle on a passed canvas with preserveDrawingBuffer
+ // and antialiasing ON, tests rect color on every iteration.
+ function createMultisampleCorruptionTest(gl) {
+ var lastContext = null;
+ // Allocate a read back buffer in advance and reuse it for all iterations
+ // to avoid memory issues because of late garbage collection.
+ var readBackBuf = new Uint8Array(gl.canvas.width * gl.canvas.height * 4);
+
+ var program = wtu.loadStandardProgram(gl);
+ var uniforms = wtu.getUniformMap(gl, program);
+ gl.useProgram(program);
+
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,2.5,0, 1.5,1.5,0, 2.5,1.5,0 ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.vertexAttrib3f(1, 0.0, 0.0, 1.0);
+
+ var identityMat = new Float32Array([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ ]);
+
+ gl.uniformMatrix4fv(uniforms.u_modelViewProjMatrix.location, false, identityMat);
+
+ function test() {
+ var gl2 = wtu.create3DContext(null, {antialias: true});
+
+ gl2.canvas.width = gl2.canvas.height = 1024;
+ gl2.canvas.style.width = gl2.canvas.style.height = "1px";
+ document.body.appendChild(gl2.canvas);
+
+ gl2.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl2.clear(gl2.COLOR_BUFFER_BIT);
+
+ if(lastContext) {
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ var msg = "Canvas should be red";
+ wtu.checkCanvasRectColor(gl,
+ 0, 0, gl.canvas.width, gl.canvas.height,
+ [255, 0, 0, 255], null,
+ function() {
+ testPassed(msg);
+ },
+ function() {
+ testFailed(msg);
+ return false;
+ },
+ debug, readBackBuf);
+ document.body.removeChild(lastContext.canvas);
+ }
+
+ lastContext = gl2;
+ return true;
+ };
+
+ // First pass does initialization
+ test();
+
+ return test;
+ }
+
+ return {
+ run: run,
+
+ createContextCreationAndDestructionTest: createContextCreationAndDestructionTest,
+ createContextCreationTest: createContextCreationTest,
+ createMultisampleCorruptionTest: createMultisampleCorruptionTest
+ };
+
+})();
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js b/dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js
new file mode 100644
index 000000000..7cc06312d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js
@@ -0,0 +1,183 @@
+/*
+** Copyright (c) 2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(extensionTypeName, extensionName, pixelType, prologue) {
+ var wtu = WebGLTestUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ var init = function()
+ {
+ description("This test verifies the functionality of the " + extensionName + " extension, if it is available.");
+
+ var canvas = document.getElementById("canvas");
+ gl = wtu.create3DContext(canvas);
+
+ if (!prologue(gl, extensionTypeName)) {
+ finishTest();
+ return;
+ }
+
+ // Before the extension is enabled
+ var extensionEnabled = false;
+ runTestSuite(extensionEnabled);
+
+ if (!gl.getExtension(extensionName))
+ testPassed("No " + extensionName + " support -- this is legal");
+ else {
+ // After the extension is enabled
+ extensionEnabled = true;
+ runTestSuite(extensionEnabled);
+ }
+
+ finishTest();
+ }
+
+ function runTestSuite(extensionEnabled)
+ {
+ var magF = [gl.NEAREST, gl.LINEAR];
+ var minF = [gl.NEAREST, gl.LINEAR, gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST_MIPMAP_LINEAR, gl.LINEAR_MIPMAP_NEAREST, gl.LINEAR_MIPMAP_LINEAR];
+ var tex2DFShader = [
+ 'uniform sampler2D tex;',
+ 'void main() {',
+ ' gl_FragData[0] = texture2D(tex, vec2(0.5, 0.5)) * vec4(4.0, 2.0, 2.0, 1);',
+ '}'].join('\n');
+
+ var positionVertexShader = [
+ 'attribute vec4 vPosition;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ '}'].join('\n');
+
+ var texCubeFShader = [
+ 'uniform samplerCube tex;',
+ 'void main() {',
+ ' gl_FragColor = textureCube(tex, normalize(vec3(0.5, 0.5, 1))) * vec4(4.0, 2.0, 2.0, 1);',
+ '}'].join('\n');
+
+ var vs = wtu.loadShader(gl, positionVertexShader, gl.VERTEX_SHADER);
+ var fs_2d = wtu.loadShader(gl, tex2DFShader, gl.FRAGMENT_SHADER);
+ var fs_cube = wtu.loadShader(gl, texCubeFShader, gl.FRAGMENT_SHADER);
+
+ // TEXTURE_2D
+ var program = wtu.setupProgram(gl, [vs, fs_2d]);
+ gl.useProgram(program);
+ wtu.setupUnitQuad(gl);
+ for (var kk = 0; kk < 2; ++kk) {
+ for (var ii = 0; ii < 6; ++ii) {
+ var linear = false;
+ if (magF[kk] == gl.LINEAR || (minF[ii] != gl.NEAREST && minF[ii] != gl.NEAREST_MIPMAP_NEAREST))
+ linear = true;
+ var color = (!extensionEnabled && linear) ? [0, 0, 0, 255] : [255, 255, 255, 255];
+ runEachTest(gl.TEXTURE_2D, magF[kk], minF[ii], linear, extensionEnabled, color);
+ }
+ }
+
+ // TEXTURE_CUBE_MAP
+ var programCube = wtu.setupProgram(gl, [vs, fs_cube]);
+ gl.useProgram(programCube);
+ wtu.setupUnitQuad(gl);
+ for (var kk = 0; kk < 2; ++kk) {
+ for (var ii = 0; ii < 6; ++ii) {
+ var linear = false;
+ if (magF[kk] == gl.LINEAR || (minF[ii] != gl.NEAREST && minF[ii] != gl.NEAREST_MIPMAP_NEAREST))
+ linear = true;
+ var color = (!extensionEnabled && linear) ? [0, 0, 0, 255] : [255, 255, 255, 255];
+ runEachTest(gl.TEXTURE_CUBE_MAP, magF[kk], minF[ii], linear, extensionEnabled, color);
+ }
+ }
+ }
+
+ function runEachTest(textureTarget, magFilter, minFilter, linear, extensionEnabled, expected)
+ {
+ var format = gl.RGBA;
+ var numberOfChannels = 4;
+ debug("");
+ debug("testing target: " + wtu.glEnumToString(gl,textureTarget) +
+ ", testing format: " + wtu.glEnumToString(gl, format) +
+ ", magFilter is: " + wtu.glEnumToString(gl, magFilter) +
+ ", minFilter is: " + wtu.glEnumToString(gl, minFilter) +
+ ", " + extensionName + " is " + (extensionEnabled ? "enabled": "not enabled")
+ );
+
+ // Generate data.
+ var width = 4;
+ var height = 4;
+ var canvas2d = document.createElement('canvas');
+ canvas2d.width = width;
+ canvas2d.height = height;
+ var ctx2d = canvas2d.getContext('2d');
+ var color = [64, 128, 128, 255];
+ ctx2d.fillStyle = "rgba(" + color[0] + "," + color[1] + "," + color[2] + "," + color[3] + ")";
+ ctx2d.fillRect(0, 0, width, height);
+
+ var texture = gl.createTexture();
+ gl.bindTexture(textureTarget, texture);
+ gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, magFilter);
+ gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, minFilter);
+ gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+
+ if (textureTarget == gl.TEXTURE_2D) {
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, format, gl[pixelType], canvas2d);
+ if (minFilter != gl.NEAREST && minFilter != gl.LINEAR) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors during texture setup");
+ gl.generateMipmap(gl.TEXTURE_2D);
+ if (gl.getError() != gl.NO_ERROR) {
+ debug("generateMipmap failed for floating-point TEXTURE_2D -- this is legal -- skipping the rest of this test");
+ return;
+ }
+ }
+ } else if (textureTarget == gl.TEXTURE_CUBE_MAP) {
+ var targets = [
+ gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ for (var tt = 0; tt < targets.length; ++tt)
+ gl.texImage2D(targets[tt], 0, format, format, gl[pixelType], canvas2d);
+ if (minFilter != gl.NEAREST && minFilter != gl.LINEAR) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors during texture setup");
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ if (gl.getError() != gl.NO_ERROR) {
+ debug("generateMipmap failed for floating-point TEXTURE_CUBE_MAP -- this is legal -- skipping the rest of this test");
+ return;
+ }
+ }
+ }
+ wtu.clearAndDrawUnitQuad(gl);
+ if (!linear) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, extensionTypeName + " texture with non-Linear filter should succeed with NO_ERROR no matter whether " + extensionName + " is enabled or not");
+ } else if (!extensionEnabled) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, extensionTypeName + " texture with Linear filter should produce [0, 0, 0, 1.0] with NO_ERROR if " + extensionName + " isn't enabled");
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, extensionTypeName + " texture with Linear filter should succeed with NO_ERROR if " + extensionTypeName + " is enabled");
+ }
+
+ wtu.checkCanvas(gl, expected, "should be " + expected[0] + "," + expected[1] + "," + expected[2] + "," + expected[3]);
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js b/dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js
new file mode 100644
index 000000000..69846cda0
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js
@@ -0,0 +1,343 @@
+/*
+** Copyright (c) 2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+'use strict';
+
+var OutOfBoundsTest = (function() {
+
+var runCommonInvalidValueTests = function(callTemplate, gl, wtu, ext) {
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: -1, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: -1}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: -1, type: 'gl.UNSIGNED_BYTE', offset: 1}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_BYTE', offset: -1}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: '0xffffffff', type: 'gl.UNSIGNED_BYTE', offset: 0}));
+};
+
+var setupProgramAndBindVertexArray = function(gl, wtu) {
+ var program = wtu.loadStandardProgram(gl);
+
+ gl.useProgram(program);
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.enableVertexAttribArray(0);
+
+ return program;
+};
+
+var setupProgram2 = function(gl, wtu) {
+ var vshader = [
+ 'attribute vec3 aOne;',
+ 'attribute vec2 aTwo;',
+ 'void main() {',
+ ' gl_Position = vec4(aOne, 1.0) + vec4(aTwo, 0.0, 1.0);',
+ '}'
+ ].join('\n');
+
+ var fshader = [
+ 'void main() {',
+ ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);',
+ '}'
+ ].join('\n');
+
+ var program = wtu.setupProgram(gl, [vshader, fshader], [ "aOne", "aTwo" ]);
+ if (!program) {
+ testFailed("failed to create test program");
+ }
+ return program;
+};
+
+var runDrawArraysTest = function(callTemplate, gl, wtu, ext) {
+ var program = setupProgramAndBindVertexArray(gl, wtu);
+
+ debug("Test empty buffer")
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ ]), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 1}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 10000}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 10000000000000}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 1, count: 0}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 0}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 100, count: 0}));
+ runCommonInvalidValueTests(callTemplate, gl, wtu, ext);
+
+ debug("")
+ debug("Test buffer with 3 float vectors")
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 3}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 3, count: 2}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 10000}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 10000000000000}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 0}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 100, count: 0}));
+ runCommonInvalidValueTests(callTemplate, gl, wtu, ext);
+
+ debug("")
+ debug("Test buffer with interleaved (3+2) float vectors")
+
+ setupProgram2(gl, wtu);
+
+ var vbo = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ // enough for 9 vertices, so 3 triangles
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*5), gl.STATIC_DRAW);
+
+ // bind first 3 elements, with a stride of 5 float elements
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 5*4, 0);
+ // bind 2 elements, starting after the first 3; same stride of 5 float elements
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 5*4, 3*4);
+
+ gl.enableVertexAttribArray(0);
+ gl.enableVertexAttribArray(1);
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9}));
+
+ // negative values must generate INVALID_VALUE; they can never be valid
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: 0, count: -500}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: -200, count: 1}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: -200, count: -500}));
+
+ // 0xffffffff needs to convert to a 'long' IDL argument as -1, as per
+ // WebIDL 4.1.7. JS ToInt32(0xffffffff) == -1. Thus INVALID_VALUE.
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: 0, count: '0xffffffff'}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: '0xffffffff', count: '0xffffffff'}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: '0xffffffff', count: 1}));
+
+ // values that could otherwise be valid but aren't due to bindings generate
+ // INVALID_OPERATION
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 200}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: '0x7fffffff'}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: '0x7fffffff', count: 1}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: '0x7fffffff', count: '0x7fffffff'}));
+};
+
+var runDrawElementsTest = function(callTemplate, gl, wtu, ext) {
+ var program = setupProgramAndBindVertexArray(gl, wtu);
+ var contextVersion = wtu.getDefault3DContextVersion();
+
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexObject = gl.createBuffer();
+
+ debug('Test empty index buffer');
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ ]), gl.STATIC_DRAW);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000000000000, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ runCommonInvalidValueTests(callTemplate, gl, wtu, ext);
+
+ debug('');
+ debug('Test buffer with 3 byte indexes');
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2 ]), gl.STATIC_DRAW);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 2}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000000000000, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ runCommonInvalidValueTests(callTemplate, gl, wtu, ext);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 4}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: '0x7fffffff', type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: '0x7fffffff', type: 'gl.UNSIGNED_BYTE', offset: '0x7fffffff'}));
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, (new Uint8Array([ 3, 0, 1, 2 ])).subarray(1), gl.STATIC_DRAW)');
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint8Array([ 3, 0, 1]))');
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, (new Uint8Array([ 3, 0, 1, 2 ])).subarray(1))');
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0}));
+
+ debug('');
+ debug('Test buffer with interleaved (3+2) float vectors');
+
+ setupProgram2(gl, wtu);
+
+ var vbo = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ // enough for 9 vertices, so 3 triangles
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*5), gl.STATIC_DRAW);
+
+ // bind first 3 elements, with a stride of 5 float elements
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 5*4, 0);
+ // bind 2 elements, starting after the first 3; same stride of 5 float elements
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 5*4, 3*4);
+
+ gl.enableVertexAttribArray(0);
+ gl.enableVertexAttribArray(1);
+
+ var ebo = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo);
+ // For WebGL 2, PRIMITIVE_RESTART_FIXED_INDEX is always enabled.
+ // 0xffff will be handled as a primitive restart.
+ if (contextVersion <= 1) {
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(
+ [ 0, 1, 2,
+ 1, 2, 0,
+ 2, 0, 1,
+ 201, 202, 203,
+ 0x7fff, 0x7fff, 0x7fff,
+ 0xffff, 0xffff, 0xffff ]),
+ gl.STATIC_DRAW);
+ } else {
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(
+ [ 0, 1, 2,
+ 1, 2, 0,
+ 2, 0, 1,
+ 201, 202, 203,
+ 0x7fff, 0x7fff, 0x7fff,
+ 0xffff - 1, 0xffff - 1, 0xffff - 1 ]),
+ gl.STATIC_DRAW);
+ }
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 9, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+
+
+ // invalid operation with indices that would be valid with correct bindings
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 9, type: 'gl.UNSIGNED_SHORT', offset: 1000}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 12, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 15, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 18, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_SHORT', offset: 2*15}));
+
+ // 0xffffffff needs to convert to a 'long' IDL argument as -1, as per
+ // WebIDL 4.1.7. JS ToInt32(0xffffffff) == -1. Thus INVALID_VALUE.
+ wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: '0xffffffff', type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ // offset is defined as GLintptr, which is long long in IDL (64-bit).
+ // 2^32 - 1 should not overflow, and only result in INVALID_OPERATION.
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_SHORT', offset: '0xffffffff'}));
+
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: '0x7fffffff', type: 'gl.UNSIGNED_SHORT', offset: 0}));
+
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+
+ // invalid operation with offset that's not a multiple of the type size
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 1}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2}));
+
+ // invalid operation if no buffer is bound to ELEMENT_ARRAY_BUFFER
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 0}));
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo);
+
+ debug('');
+ debug('Test buffer setting attrib 0 to a buffer too small and disable it.');
+ var smallVBO = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, smallVBO);
+ gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0x10);
+ gl.disableVertexAttribArray(0);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2}));
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2}));
+};
+
+var runInstancedTest = function(callTemplate, gl, wtu, ext) {
+ setupProgram2(gl, wtu);
+
+ // Initialize non-instanced attribute data.
+ // Enough for 9 vertices, so 3 triangles.
+ var vbo = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*3), gl.STATIC_DRAW);
+
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ // Setup buffer for instanced attribute data.
+ var vbo2 = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo2);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+ gl.enableVertexAttribArray(0);
+ gl.enableVertexAttribArray(1);
+
+ debug('Test out-of-range instanced attributes');
+ debug('');
+
+ debug('Test with an empty buffer for the instanced attribute');
+ ext.vertexAttribDivisorANGLE(1, 1);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 0}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 10000, primcount: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1}));
+
+ debug('Test with a buffer with 1 float for the instanced attribute');
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(1), gl.STATIC_DRAW);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 0}));
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 10000, primcount: 0}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1}));
+
+ debug('');
+ debug('Test with a buffer with 2 floats for the instanced attribute');
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(2), gl.STATIC_DRAW);
+ debug('Divisor 1');
+ ext.vertexAttribDivisorANGLE(1, 1);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 2}));
+ debug('Divisor 3');
+ ext.vertexAttribDivisorANGLE(1, 3);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 3}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 4}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 10000}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: '0x7fffffff'}));
+
+ debug('');
+ debug('Test with a buffer with 4 floats for the instanced attribute');
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(4), gl.STATIC_DRAW);
+ debug('Divisor 1');
+ ext.vertexAttribDivisorANGLE(1, 1);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 2}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 3}));
+ debug('Divisor 2');
+ ext.vertexAttribDivisorANGLE(1, 2);
+ wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 4}));
+ wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 5}));
+};
+
+var runDrawArraysInstancedTest = function(callTemplate, gl, wtu, ext) {
+ runInstancedTest(callTemplate, gl, wtu, ext);
+};
+
+var runDrawElementsInstancedTest = function(callTemplate, gl, wtu, ext) {
+ var ebo = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(
+ [ 0, 1, 2,
+ 5, 4, 3,
+ 6, 7, 8 ]),
+ gl.STATIC_DRAW);
+ callTemplate = wtu.replaceParams(callTemplate, {type: 'gl.UNSIGNED_BYTE', offset: '$(offset)', count: '$(count)', primcount: '$(primcount)'});
+ runInstancedTest(callTemplate, gl, wtu, ext);
+};
+
+return {
+ runDrawArraysTest: runDrawArraysTest,
+ runDrawArraysInstancedTest: runDrawArraysInstancedTest,
+ runDrawElementsTest: runDrawElementsTest,
+ runDrawElementsInstancedTest: runDrawElementsInstancedTest
+};
+
+})();
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js
new file mode 100644
index 000000000..33ab722d4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js
@@ -0,0 +1,329 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var realRedColor = [255, 0, 0];
+ var realGreenColor = [0, 255, 0];
+ var realBlueColor = [0, 0, 255];
+ var realCyanColor = [0, 255, 255];
+ var redColor = realRedColor;
+ var greenColor = realGreenColor;
+ var blueColor = realBlueColor;
+ var cyanColor = realCyanColor;
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking a sub-rectangle of a canvas (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+
+ // The sub-rectangle tests only apply to WebGL 2.0 for the
+ // time being, though the tests for the WebGL 1.0
+ // format/internal format/type combinations are generated into
+ // conformance/textures/.
+ if (wtu.getDefault3DContextVersion() < 2) {
+ debug('Test only applies to WebGL 2.0');
+ finishTest();
+ return;
+ }
+
+ gl = wtu.create3DContext("example", { preserveDrawingBuffer: true });
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ blueColor = [0, 0, 0];
+ cyanColor = [0, 0, 0];
+ break;
+
+ case gl.RG:
+ case gl.RG_INTEGER:
+ blueColor = [0, 0, 0];
+ cyanColor = [0, 255, 0];
+ break;
+
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ var canvas2d = document.createElement('canvas');
+ runTest(canvas2d, setupSourceCanvas2D, '2D-rendered canvas');
+
+ var canvasWebGL = document.createElement('canvas');
+ runTest(canvasWebGL, setupSourceCanvasWebGL, 'WebGL-rendered canvas');
+
+ finishTest();
+ }
+
+ function fillStyle2D(ctx, color) {
+ ctx.fillStyle = 'rgb(' + color[0] + ', ' + color[1] + ', ' + color[2] + ')';
+ }
+
+ function setupSourceCanvas2D(canvas) {
+ var width = canvas.width;
+ var height = canvas.height;
+ var halfWidth = Math.floor(width / 2);
+ var halfHeight = Math.floor(height / 2);
+
+ var ctx = canvas.getContext('2d');
+ // Always use the same pattern for this test: four quadrants:
+ // red green
+ // blue cyan
+ // Handle odd-sized canvases
+ fillStyle2D(ctx, realRedColor);
+ ctx.fillRect(0, 0, halfWidth, halfHeight);
+ fillStyle2D(ctx, realGreenColor);
+ ctx.fillRect(halfWidth, 0, width - halfWidth, halfHeight);
+ fillStyle2D(ctx, realBlueColor);
+ ctx.fillRect(0, halfHeight, halfWidth, height - halfHeight);
+ fillStyle2D(ctx, realCyanColor);
+ ctx.fillRect(halfWidth, halfHeight, width - halfWidth, height - halfHeight);
+ }
+
+ function clearColorWebGL(ctx, color) {
+ ctx.clearColor(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0, 1.0);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ }
+
+ function setupSourceCanvasWebGL(canvas) {
+ var width = canvas.width;
+ var height = canvas.height;
+ var halfWidth = Math.floor(width / 2);
+ var halfHeight = Math.floor(height / 2);
+
+ var ctx = canvas.getContext('webgl');
+ // Always use the same pattern for this test: four quadrants:
+ // red green
+ // blue cyan
+ // Handle odd-sized canvases
+
+ ctx.viewport(0, 0, width, height);
+ ctx.enable(ctx.SCISSOR_TEST);
+ // OpenGL origin is lower-left
+ ctx.scissor(0, 0, halfWidth, halfHeight);
+ clearColorWebGL(ctx, realBlueColor);
+ ctx.scissor(halfWidth, 0, width - halfWidth, halfHeight);
+ clearColorWebGL(ctx, realCyanColor);
+ ctx.scissor(0, halfHeight, halfWidth, height - halfHeight);
+ clearColorWebGL(ctx, realRedColor);
+ ctx.scissor(halfWidth, halfHeight, width - halfWidth, height - halfHeight);
+ clearColorWebGL(ctx, realGreenColor);
+ }
+
+ function runOneIteration(sourceDescription, useTexSubImage2D, flipY,
+ canvas, canvasSize, canvasSetupFunction,
+ sourceSubRectangle, expected,
+ bindingTarget, program)
+ {
+ sourceSubRectangleString = '';
+ if (sourceSubRectangle) {
+ sourceSubRectangleString = ', sourceSubRectangle=' + sourceSubRectangle;
+ }
+ debug('');
+ debug('Testing ' + sourceDescription + ' with ' +
+ (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ', flipY=' + flipY +
+ ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') +
+ sourceSubRectangleString);
+
+ var loc;
+ var skipCorner = false;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ switch (gl[pixelFormat]) {
+ case gl.RED_INTEGER:
+ case gl.RG_INTEGER:
+ case gl.RGB_INTEGER:
+ case gl.RGBA_INTEGER:
+ // https://github.com/KhronosGroup/WebGL/issues/1819
+ skipCorner = true;
+ break;
+ }
+ }
+
+ if (skipCorner && sourceSubRectangle &&
+ sourceSubRectangle[2] == 1 && sourceSubRectangle[3] == 1) {
+ debug("Test skipped, see WebGL#1819");
+ return;
+ }
+
+ // Initialize the contents of the source canvas.
+ var width = canvasSize[0];
+ var height = canvasSize[1];
+ var halfWidth = Math.floor(width / 2);
+ var halfHeight = Math.floor(height / 2);
+ canvas.width = width;
+ canvas.height = height;
+ canvasSetupFunction(canvas);
+
+ // Upload the source canvas to the texture and draw it to a quad.
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Enable writes to the RGBA channels
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ var targets = [gl.TEXTURE_2D];
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ }
+ // In this test, this is always specified. It's currently WebGL 2.0-specific.
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
+ // Upload the image into the texture
+ var uploadWidth = sourceSubRectangle[2];
+ var uploadHeight = sourceSubRectangle[3];
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (useTexSubImage2D) {
+ // Initialize the texture to black first
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ uploadWidth, uploadHeight, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0,
+ uploadWidth, uploadHeight,
+ gl[pixelFormat], gl[pixelType], canvas);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ uploadWidth, uploadHeight, 0,
+ gl[pixelFormat], gl[pixelType], canvas);
+ }
+ }
+
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+
+ // The tests are constructed to upload a single solid color
+ // out of the canvas.
+ var outputCanvasWidth = gl.drawingBufferWidth;
+ var outputCanvasHeight = gl.drawingBufferHeight;
+ var outputCanvasHalfWidth = Math.floor(outputCanvasWidth / 2);
+ var outputCanvasHalfHeight = Math.floor(outputCanvasHeight / 2);
+ var top = 0;
+ var bottom = outputCanvasHeight - outputCanvasHalfHeight;
+ var left = 0;
+ var right = outputCanvasWidth - outputCanvasHalfWidth;
+
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+
+ // Check the four quadrants and make sure they have the right color.
+ // This is split up into four tests only because of the driver bug above.
+ var msg = 'should be ' + expected;
+ wtu.checkCanvasRect(gl, left, top, outputCanvasHalfWidth, outputCanvasHalfHeight, expected, msg);
+ if (!skipCorner) {
+ wtu.checkCanvasRect(gl, right, top, outputCanvasHalfWidth, outputCanvasHalfHeight, expected, msg);
+ }
+ wtu.checkCanvasRect(gl, left, bottom, outputCanvasHalfWidth, outputCanvasHalfHeight, expected, msg);
+ if (!skipCorner) {
+ wtu.checkCanvasRect(gl, right, bottom, outputCanvasHalfWidth, outputCanvasHalfHeight, expected, msg);
+ }
+ }
+ }
+
+ function runTest(canvas, canvasSetupFunction, sourceDescription)
+ {
+ var program = tiu.setupTexturedQuad(gl, internalFormat);
+ runTestOnBindingTarget(gl.TEXTURE_2D, program, canvas, canvasSetupFunction, sourceDescription);
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ runTestOnBindingTarget(gl.TEXTURE_CUBE_MAP, program, canvas, canvasSetupFunction, sourceDescription);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ }
+
+ function runTestOnBindingTarget(bindingTarget, program, canvas, canvasSetupFunction, sourceDescription) {
+ var cases = [
+ // Small canvas cases. Expected that these won't be
+ // GPU-accelerated in most browsers' implementations.
+ { expected: redColor, flipY: false, size: [2, 2], subRect: [0, 0, 1, 1] },
+ { expected: greenColor, flipY: false, size: [2, 2], subRect: [1, 0, 1, 1] },
+ { expected: blueColor, flipY: false, size: [2, 2], subRect: [0, 1, 1, 1] },
+ { expected: cyanColor, flipY: false, size: [2, 2], subRect: [1, 1, 1, 1] },
+ { expected: redColor, flipY: true, size: [2, 2], subRect: [0, 1, 1, 1] },
+ { expected: greenColor, flipY: true, size: [2, 2], subRect: [1, 1, 1, 1] },
+ { expected: blueColor, flipY: true, size: [2, 2], subRect: [0, 0, 1, 1] },
+ { expected: cyanColor, flipY: true, size: [2, 2], subRect: [1, 0, 1, 1] },
+
+ // Larger canvas cases. Expected that these will be
+ // GPU-accelerated in most browsers' implementations.
+ // Changes will be gladly accepted to trigger more
+ // browsers' heuristics to accelerate these canvases.
+ { expected: redColor, flipY: false, size: [384, 384], subRect: [ 0, 0, 192, 192] },
+ { expected: greenColor, flipY: false, size: [384, 384], subRect: [192, 0, 192, 192] },
+ { expected: blueColor, flipY: false, size: [384, 384], subRect: [ 0, 192, 192, 192] },
+ { expected: cyanColor, flipY: false, size: [384, 384], subRect: [192, 192, 192, 192] },
+ { expected: blueColor, flipY: true, size: [384, 384], subRect: [ 0, 0, 192, 192] },
+ { expected: cyanColor, flipY: true, size: [384, 384], subRect: [192, 0, 192, 192] },
+ { expected: redColor, flipY: true, size: [384, 384], subRect: [ 0, 192, 192, 192] },
+ { expected: greenColor, flipY: true, size: [384, 384], subRect: [192, 192, 192, 192] },
+
+ ];
+
+ for (var i in cases) {
+ runOneIteration(sourceDescription, false, cases[i].flipY,
+ canvas, cases[i].size, canvasSetupFunction,
+ cases[i].subRect,
+ cases[i].expected, bindingTarget, program);
+
+ // In Chrome, this hits a bug on Mac with Intel GPU.
+ // Chromium bug: crbug.com/665656
+ // Apple Radar: 29563996
+ //runOneIteration(sourceDescription, true, cases[i].flipY,
+ // canvas, cases[i].size, canvasSetupFunction,
+ // cases[i].subRect,
+ // cases[i].expected, bindingTarget, program);
+ }
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js
new file mode 100644
index 000000000..4024a0200
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js
@@ -0,0 +1,320 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var whiteColor = [255, 255, 255, 255];
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ whiteColor = [255, 0, 0, 255];
+ greenColor = [0, 0, 0];
+ break;
+ case gl.RG:
+ case gl.RG_INTEGER:
+ whiteColor = [255, 255, 0, 255];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var testCanvas = document.createElement('canvas');
+ runTest(testCanvas);
+ //document.body.appendChild(testCanvas);
+ }
+
+ function setCanvasToRedGreen(ctx) {
+ var width = ctx.canvas.width;
+ var height = ctx.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ ctx.fillStyle = "#ff0000";
+ ctx.fillRect(0, 0, width, halfHeight);
+ ctx.fillStyle = "#00ff00";
+ ctx.fillRect(0, halfHeight, width, height - halfHeight);
+ }
+
+ function drawTextInCanvas(ctx, bindingTarget) {
+ var width = ctx.canvas.width;
+ var height = ctx.canvas.height;
+ ctx.fillStyle = "#ffffff";
+ ctx.fillRect(0, 0, width, height);
+ ctx.font = '20pt Arial';
+ ctx.fillStyle = 'black';
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.fillText("1234567890", width / 2, height / 4);
+ }
+
+ function setCanvasTo257x257(ctx, bindingTarget) {
+ ctx.canvas.width = 257;
+ ctx.canvas.height = 257;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function setCanvasToMin(ctx, bindingTarget) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ // cube map texture must be square.
+ ctx.canvas.width = 2;
+ } else {
+ ctx.canvas.width = 1;
+ }
+ ctx.canvas.height = 2;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function checkSourceCanvasImageData(imageDataBefore, imageDataAfter) {
+ if (imageDataBefore.length != imageDataAfter.length) {
+ testFailed("The size of image data in source canvas become different after it is used in webgl texture.");
+ return;
+ }
+ for (var i = 0; i < imageDataAfter.length; i++) {
+ if (imageDataBefore[i] != imageDataAfter[i]) {
+ testFailed("Pixel values in source canvas have changed after canvas used in webgl texture.");
+ return;
+ }
+ }
+ testPassed("Pixel values in source canvas remain unchanged after canvas used in webgl texture.");
+ }
+
+ function runOneIteration(canvas, useTexSubImage2D, flipY, program, bindingTarget, opt_texture, opt_fontTest)
+ {
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with flipY=' + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') +
+ ' canvas size: ' + canvas.width + 'x' + canvas.height +
+ (opt_fontTest ? " with fonts" : " with red-green"));
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ if (!opt_texture) {
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ } else {
+ var texture = opt_texture;
+ }
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ var targets = [gl.TEXTURE_2D];
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ }
+ // Upload the image into the texture
+ for (var tt = 0; tt < targets.length; ++tt) {
+ // Initialize the texture to black first
+ if (useTexSubImage2D) {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], canvas.width, canvas.height, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], canvas);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], canvas);
+ }
+ }
+
+ var width = gl.canvas.width;
+ var height = gl.canvas.height;
+ var halfWidth = Math.floor(width / 2);
+ var halfHeight = Math.floor(height / 2);
+ var top = flipY ? 0 : (height - halfHeight);
+ var bottom = flipY ? (height - halfHeight) : 0;
+
+ var loc;
+ var skipCorner = false;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ switch (gl[pixelFormat]) {
+ case gl.RED_INTEGER:
+ case gl.RG_INTEGER:
+ case gl.RGB_INTEGER:
+ case gl.RGBA_INTEGER:
+ // https://github.com/KhronosGroup/WebGL/issues/1819
+ skipCorner = true;
+ break;
+ }
+ }
+
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]);
+
+ if (opt_fontTest) {
+ // check half is a solid color.
+ wtu.checkCanvasRect(
+ gl, 0, top, width, halfHeight,
+ whiteColor,
+ "should be white");
+ // check other half is not a solid color.
+ wtu.checkCanvasRectColor(
+ gl, 0, bottom, width, halfHeight,
+ whiteColor, 0,
+ function() {
+ testFailed("font missing");
+ },
+ function() {
+ testPassed("font rendered");
+ },
+ debug);
+ } else {
+ // Check the top and bottom halves and make sure they have the right color.
+ debug("Checking " + (flipY ? "top" : "bottom"));
+ wtu.checkCanvasRect(gl, 0, bottom, (skipCorner && flipY) ? halfWidth : width, halfHeight, redColor,
+ "shouldBe " + redColor);
+ debug("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, 0, top, (skipCorner && !flipY) ? halfWidth : width, halfHeight, greenColor,
+ "shouldBe " + greenColor);
+ }
+
+ if (!useTexSubImage2D && pixelFormat == "RGBA") {
+ if (pixelType == "FLOAT") {
+ // Attempt to set a pixel in the texture to ensure the texture was
+ // actually created with floats. Regression test for http://crbug.com/484968
+ var pixels = new Float32Array([1000.0, 1000.0, 1000.0, 1000.0]);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, 1, 1, gl[pixelFormat], gl[pixelType], pixels);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Texture should be backed by floats");
+ } else if (pixelType == "HALF_FLOAT_OES" || pixelType == "HALF_FLOAT") {
+ // Attempt to set a pixel in the texture to ensure the texture was
+ // actually created with half-floats. Regression test for http://crbug.com/484968
+ var halfFloatTenK = 0x70E2; // Half float 10000
+ var pixels = new Uint16Array([halfFloatTenK, halfFloatTenK, halfFloatTenK, halfFloatTenK]);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, 1, 1, gl[pixelFormat], gl[pixelType], pixels);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Texture should be backed by half-floats");
+ }
+ }
+ }
+
+ if (false) {
+ var m = wtu.makeImageFromCanvas(gl.canvas);
+ document.getElementById("console").appendChild(m);
+ document.getElementById("console").appendChild(document.createElement("hr"));
+ }
+
+ return texture;
+ }
+
+ function runTest(canvas)
+ {
+ var ctx = canvas.getContext("2d");
+
+ var cases = [
+ { sub: false, flipY: true, font: false, init: setCanvasToMin },
+ { sub: false, flipY: false, font: false },
+ { sub: true, flipY: true, font: false },
+ { sub: true, flipY: false, font: false },
+ { sub: false, flipY: true, font: false, init: setCanvasTo257x257 },
+ { sub: false, flipY: false, font: false },
+ { sub: true, flipY: true, font: false },
+ { sub: true, flipY: false, font: false },
+ { sub: false, flipY: true, font: true, init: drawTextInCanvas },
+ { sub: false, flipY: false, font: true },
+ { sub: true, flipY: true, font: true },
+ { sub: true, flipY: false, font: true },
+ ];
+
+ function runTexImageTest(bindingTarget) {
+ var program;
+ if (bindingTarget == gl.TEXTURE_2D) {
+ program = tiu.setupTexturedQuad(gl, internalFormat);
+ } else {
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ }
+
+ return new Promise(function(resolve, reject) {
+ var count = 4;
+ var caseNdx = 0;
+ var texture = undefined;
+ function runNextTest() {
+ var c = cases[caseNdx];
+ var imageDataBefore = null;
+ if (c.init) {
+ c.init(ctx, bindingTarget);
+ imageDataBefore = ctx.getImageData(0, 0, canvas.width, canvas.height);
+ }
+ texture = runOneIteration(canvas, c.sub, c.flipY, program, bindingTarget, texture, c.font);
+ if (c.init) {
+ debug("Checking if pixel values in source canvas change after canvas used as webgl texture");
+ checkSourceCanvasImageData(imageDataBefore, ctx.getImageData(0, 0, canvas.width, canvas.height));
+ }
+ // for the first 2 iterations always make a new texture.
+ if (count > 2) {
+ gl.deleteTexture(texture);
+ texture = undefined;
+ }
+ ++caseNdx;
+ if (caseNdx == cases.length) {
+ caseNdx = 0;
+ --count;
+ if (!count) {
+ resolve("SUCCESS");
+ return;
+ }
+ }
+ wtu.waitForComposite(runNextTest);
+ }
+ runNextTest();
+ });
+ }
+
+ runTexImageTest(gl.TEXTURE_2D).then(function(val) {
+ runTexImageTest(gl.TEXTURE_CUBE_MAP).then(function(val) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ });
+ });
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js
new file mode 100644
index 000000000..2b8d04740
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js
@@ -0,0 +1,63 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from a Blob (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", resourcePath + "red-green-semi-transparent.png");
+ xhr.responseType = 'blob';
+ xhr.send();
+ xhr.onload = function() {
+ var blob = xhr.response;
+ runImageBitmapTest(blob, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ finishTest();
+ }
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js
new file mode 100644
index 000000000..98ec219c9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js
@@ -0,0 +1,89 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from an HTMLCanvasElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var testCanvas = document.createElement('canvas');
+ var ctx = testCanvas.getContext("2d");
+ setCanvasToMin(ctx);
+ runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+
+ setCanvasTo257x257(ctx);
+ runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ finishTest();
+ }
+
+ function setCanvasToRedGreen(ctx) {
+ var width = ctx.canvas.width;
+ var halfWidth = Math.floor(width / 2);
+ var height = ctx.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ ctx.fillStyle = "rgba(255, 0, 0, 1)";
+ ctx.fillRect(0, 0, halfWidth, halfHeight);
+ ctx.fillStyle = "rgba(255, 0, 0, 0.5)";
+ ctx.fillRect(halfWidth, 0, halfWidth, halfHeight);
+ ctx.fillStyle = "rgba(0, 255, 0, 1)";
+ ctx.fillRect(0, halfHeight, halfWidth, halfHeight);
+ ctx.fillStyle = "rgba(0, 255, 0, 0.5)";
+ ctx.fillRect(halfWidth, halfHeight, halfWidth, halfHeight);
+ }
+
+ function setCanvasToMin(ctx) {
+ ctx.canvas.width = 2;
+ ctx.canvas.height = 2;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function setCanvasTo257x257(ctx) {
+ ctx.canvas.width = 257;
+ ctx.canvas.height = 257;
+ setCanvasToRedGreen(ctx);
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js
new file mode 100644
index 000000000..6c07b5dbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js
@@ -0,0 +1,67 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from an ImageBitmap (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ var imageData = new ImageData(new Uint8ClampedArray(
+ [255, 0, 0, 255,
+ 255, 0, 0, 0,
+ 0, 255, 0, 255,
+ 0, 255, 0, 0]),
+ 2, 2);
+
+ createImageBitmap(imageData, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(bitmap) {
+ // bitmap is in unpremultiplied form
+ runImageBitmapTest(bitmap, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ finishTest();
+ });
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js
new file mode 100644
index 000000000..1c26db6ef
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js
@@ -0,0 +1,64 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ var imageData = new ImageData(new Uint8ClampedArray(
+ [255, 0, 0, 255,
+ 255, 0, 0, 0,
+ 0, 255, 0, 255,
+ 0, 255, 0, 0]),
+ 2, 2);
+
+ runImageBitmapTest(imageData, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ finishTest();
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js
new file mode 100644
index 000000000..e242b8606
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js
@@ -0,0 +1,61 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from an HTMLImageElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var image = new Image();
+ image.onload = function() {
+ bufferedLogToConsole("Source image has been loaded");
+ runImageBitmapTest(image, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ finishTest();
+ }
+ image.src = resourcePath + "red-green-semi-transparent.png";
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js
new file mode 100644
index 000000000..1ef2dabe2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js
@@ -0,0 +1,61 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from an HTMLVideoElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var video = document.createElement("video");
+ video.oncanplaythrough = function() {
+ runImageBitmapTest(video, 1, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false);
+ finishTest();
+ }
+ video.src = resourcePath + "red-green.theora.ogv";
+ document.body.appendChild(video);
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js
new file mode 100644
index 000000000..80abb697c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js
@@ -0,0 +1,267 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var imageData = null;
+ var blackColor = [0, 0, 0];
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ var canvas2d = document.getElementById("texcanvas");
+ var context2d = canvas2d.getContext("2d");
+ imageData = context2d.createImageData(2, 2);
+ var data = imageData.data;
+ data[0] = 255;
+ data[1] = 0;
+ data[2] = 0;
+ data[3] = 255;
+ data[4] = 255;
+ data[5] = 0;
+ data[6] = 0;
+ data[7] = 0;
+ data[8] = 0;
+ data[9] = 255;
+ data[10] = 0;
+ data[11] = 255;
+ data[12] = 0;
+ data[13] = 255;
+ data[14] = 0;
+ data[15] = 0;
+
+ runTest();
+ }
+
+ function runOneIteration(useTexSubImage2D, flipY, premultiplyAlpha,
+ sourceSubRectangle, expected,
+ bindingTarget, program)
+ {
+ sourceSubRectangleString = '';
+ if (sourceSubRectangle) {
+ sourceSubRectangleString = ', sourceSubRectangle=' + sourceSubRectangle;
+ }
+ debug('');
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with flipY=' + flipY + ' and premultiplyAlpha=' + premultiplyAlpha +
+ ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') +
+ sourceSubRectangleString);
+
+ var loc;
+ var skipCorner = false;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ switch (gl[pixelFormat]) {
+ case gl.RED_INTEGER:
+ case gl.RG_INTEGER:
+ case gl.RGB_INTEGER:
+ case gl.RGBA_INTEGER:
+ // https://github.com/KhronosGroup/WebGL/issues/1819
+ skipCorner = true;
+ break;
+ }
+ }
+
+ if (skipCorner && expected.length == 1 && (flipY ^ sourceSubRectangle[1] == 0)) {
+ debug("Test skipped, see WebGL#1819");
+ return;
+ }
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Enable writes to the RGBA channels
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
+ var targets = [gl.TEXTURE_2D];
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ }
+ // Handle the source sub-rectangle if specified (WebGL 2.0 only)
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
+ }
+ // Upload the image into the texture
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (sourceSubRectangle) {
+ if (useTexSubImage2D) {
+ // Initialize the texture to black first
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ sourceSubRectangle[2], sourceSubRectangle[3], 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0,
+ sourceSubRectangle[2], sourceSubRectangle[3],
+ gl[pixelFormat], gl[pixelType], imageData);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ sourceSubRectangle[2], sourceSubRectangle[3], 0,
+ gl[pixelFormat], gl[pixelType], imageData);
+ }
+ } else {
+ if (useTexSubImage2D) {
+ // Initialize the texture to black first
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], imageData.width, imageData.height, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], imageData);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], imageData);
+ }
+ }
+ }
+
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ }
+
+ var width = gl.canvas.width;
+ var halfWidth = Math.floor(width / 2);
+ var height = gl.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+
+ var top = 0;
+ var bottom = height - halfHeight;
+ var left = 0;
+ var right = width - halfWidth;
+
+ var tl, tr, bl, br;
+ if (expected.length == 1) {
+ tl = tr = bl = br = expected[0];
+ } else {
+ tl = expected[0];
+ tr = expected[1];
+ bl = expected[2];
+ br = expected[3];
+ }
+
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+
+ // Check the top pixel and bottom pixel and make sure they have
+ // the right color.
+ wtu.checkCanvasRect(gl, left, top, halfWidth, halfHeight, tl, "shouldBe " + tl);
+ if (!skipCorner) {
+ wtu.checkCanvasRect(gl, right, top, halfWidth, halfHeight, tr, "shouldBe " + tr);
+ }
+ wtu.checkCanvasRect(gl, left, bottom, halfWidth, halfHeight, bl, "shouldBe " + bl);
+ if (!skipCorner) {
+ wtu.checkCanvasRect(gl, right, bottom, halfWidth, halfHeight, br, "shouldBe " + br);
+ }
+ }
+ }
+
+ function runTest()
+ {
+ var program = tiu.setupTexturedQuad(gl, internalFormat);
+ runTestOnBindingTarget(gl.TEXTURE_2D, program);
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ runTestOnBindingTarget(gl.TEXTURE_CUBE_MAP, program);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ }
+
+ function runTestOnBindingTarget(bindingTarget, program) {
+ var k = blackColor;
+ var r = redColor;
+ var g = greenColor;
+ var cases = [
+ { expected: [r, r, g, g], flipY: false, premultiplyAlpha: false, sub: false },
+ { expected: [r, r, g, g], flipY: false, premultiplyAlpha: false, sub: true },
+ { expected: [r, k, g, k], flipY: false, premultiplyAlpha: true, sub: false },
+ { expected: [r, k, g, k], flipY: false, premultiplyAlpha: true, sub: true },
+ { expected: [g, g, r, r], flipY: true, premultiplyAlpha: false, sub: false },
+ { expected: [g, g, r, r], flipY: true, premultiplyAlpha: false, sub: true },
+ { expected: [g, k, r, k], flipY: true, premultiplyAlpha: true, sub: false },
+ { expected: [g, k, r, k], flipY: true, premultiplyAlpha: true, sub: true },
+ ];
+
+ if (wtu.getDefault3DContextVersion() > 1) {
+ var morecases = [];
+ // Make 2 copies of the original case: top left and bottom right 1x1 rectangles
+ for (var i = 0; i < cases.length; i++) {
+ for (var subX = 0; subX <= 1; subX++) {
+ var subY = subX == 0 ? 1 : 0;
+ // shallow-copy cases[i] into newcase
+ var newcase = Object.assign({}, cases[i]);
+ newcase.expected = [cases[i].expected[subY * 2 + subX]];
+ newcase.sourceSubRectangle = [subX, subY, 1, 1];
+ morecases.push(newcase);
+ }
+ }
+ cases = cases.concat(morecases);
+ }
+
+ for (var i in cases) {
+ runOneIteration(cases[i].sub, cases[i].flipY, cases[i].premultiplyAlpha,
+ cases[i].sourceSubRectangle, cases[i].expected,
+ bindingTarget, program);
+ }
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js
new file mode 100644
index 000000000..51de6018d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js
@@ -0,0 +1,263 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var imgCanvas;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking image elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ wtu.loadTexture(gl, resourcePath + "red-green.png", runTest);
+ }
+
+ function runOneIteration(image, useTexSubImage2D, flipY, topColor, bottomColor,
+ sourceSubRectangle, bindingTarget, program)
+ {
+ sourceSubRectangleString = '';
+ if (sourceSubRectangle) {
+ sourceSubRectangleString = ' sourceSubRectangle=' + sourceSubRectangle;
+ }
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with ' + image.width + 'x' + image.height + ' flipY=' + flipY + ' bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') +
+ sourceSubRectangleString);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ var targets = [gl.TEXTURE_2D];
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ }
+ // Handle the source sub-rectangle if specified (WebGL 2.0 only)
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
+ }
+ // Upload the image into the texture
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (sourceSubRectangle) {
+ if (useTexSubImage2D) {
+ // Initialize the texture to black first
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ sourceSubRectangle[2], sourceSubRectangle[3], 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0,
+ sourceSubRectangle[2], sourceSubRectangle[3],
+ gl[pixelFormat], gl[pixelType], image);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ sourceSubRectangle[2], sourceSubRectangle[3], 0,
+ gl[pixelFormat], gl[pixelType], image);
+ }
+ } else {
+ if (useTexSubImage2D) {
+ // Initialize the texture to black first
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], image.width, image.height, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], image);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], image);
+ }
+ }
+ }
+
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ }
+
+ var loc;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ }
+
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ // Check a few pixels near the top and bottom and make sure they have
+ // the right color.
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor,
+ "shouldBe " + bottomColor);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor,
+ "shouldBe " + topColor);
+ }
+ }
+
+ function runTestOnImage(image) {
+ var cases = [
+ { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor },
+ { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor },
+ { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor },
+ { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor },
+ ];
+
+
+ if (wtu.getDefault3DContextVersion() > 1) {
+ cases = cases.concat([
+ { sub: false, flipY: false, topColor: redColor, bottomColor: redColor,
+ sourceSubRectangle: [0, 0, 1, 1] },
+ { sub: false, flipY: true, topColor: greenColor, bottomColor: greenColor,
+ sourceSubRectangle: [0, 0, 1, 1] },
+ { sub: false, flipY: false, topColor: greenColor, bottomColor: greenColor,
+ sourceSubRectangle: [0, 1, 1, 1] },
+ { sub: false, flipY: true, topColor: redColor, bottomColor: redColor,
+ sourceSubRectangle: [0, 1, 1, 1] },
+ { sub: true, flipY: false, topColor: redColor, bottomColor: redColor,
+ sourceSubRectangle: [0, 0, 1, 1] },
+ { sub: true, flipY: true, topColor: greenColor, bottomColor: greenColor,
+ sourceSubRectangle: [0, 0, 1, 1] },
+ { sub: true, flipY: false, topColor: greenColor, bottomColor: greenColor,
+ sourceSubRectangle: [0, 1, 1, 1] },
+ { sub: true, flipY: true, topColor: redColor, bottomColor: redColor,
+ sourceSubRectangle: [0, 1, 1, 1] },
+ ]);
+ }
+
+ var program = tiu.setupTexturedQuad(gl, internalFormat);
+ for (var i in cases) {
+ runOneIteration(image, cases[i].sub, cases[i].flipY,
+ cases[i].topColor, cases[i].bottomColor,
+ cases[i].sourceSubRectangle,
+ gl.TEXTURE_2D, program);
+ }
+ // cube map texture must be square.
+ if (image.width != image.height)
+ return;
+ // Skip sub-rectangle tests for cube map textures for the moment.
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ for (var i in cases) {
+ if (!cases[i].sourceSubRectangle) {
+ runOneIteration(image, cases[i].sub, cases[i].flipY,
+ cases[i].topColor, cases[i].bottomColor,
+ undefined,
+ gl.TEXTURE_CUBE_MAP, program);
+ }
+ }
+ }
+
+ function runTest(image)
+ {
+ runTestOnImage(image);
+
+ imgCanvas = document.createElement("canvas");
+ imgCanvas.width = 2;
+ imgCanvas.height = 2;
+ var imgCtx = imgCanvas.getContext("2d");
+ var imgData = imgCtx.createImageData(2, 2);
+ imgData.data[0] = redColor[0];
+ imgData.data[1] = redColor[1];
+ imgData.data[2] = redColor[2];
+ imgData.data[3] = 255;
+ imgData.data[4] = redColor[0];
+ imgData.data[5] = redColor[1];
+ imgData.data[6] = redColor[2];
+ imgData.data[7] = 255;
+ imgData.data[8] = greenColor[0];
+ imgData.data[9] = greenColor[1];
+ imgData.data[10] = greenColor[2];
+ imgData.data[11] = 255;
+ imgData.data[12] = greenColor[0];
+ imgData.data[13] = greenColor[1];
+ imgData.data[14] = greenColor[2];
+ imgData.data[15] = 255;
+ imgCtx.putImageData(imgData, 0, 0);
+
+ // apparently Image is different than <img>.
+ var newImage = new Image();
+ newImage.onload = function() {
+ runTest2(newImage);
+ };
+ newImage.onerror = function() {
+ testFailed("Creating image from canvas failed. Image src: " + this.src);
+ finishTest();
+ };
+ newImage.src = imgCanvas.toDataURL();
+ }
+
+ function runTest2(image) {
+ runTestOnImage(image);
+
+ wtu.makeImageFromCanvas(imgCanvas, function() {
+ runTest3(this);
+ });
+ }
+
+ function runTest3(image) {
+ runTestOnImage(image);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js
new file mode 100644
index 000000000..be5a845b1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js
@@ -0,0 +1,148 @@
+/*
+** Copyright (c) 2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var imgCanvas;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking SVG image elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ wtu.loadTexture(gl, resourcePath + "red-green.svg", runTest);
+ }
+
+ function runOneIteration(image, useTexSubImage2D, flipY, topColor, bottomColor, bindingTarget, program)
+ {
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with flipY=' + flipY + ' bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP'));
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ var targets = [gl.TEXTURE_2D];
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ }
+ // Upload the image into the texture
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (useTexSubImage2D) {
+ // Initialize the texture to black first
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], image.width, image.height, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], image);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], image);
+ }
+ }
+
+ var loc;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ }
+
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ // Check a few pixels near the top and bottom and make sure they have
+ // the right color.
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor,
+ "shouldBe " + bottomColor);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor,
+ "shouldBe " + topColor);
+ }
+ }
+
+ function runTest(image)
+ {
+ var program = tiu.setupTexturedQuad(gl, internalFormat);
+ runTestOnBindingTarget(image, gl.TEXTURE_2D, program);
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ runTestOnBindingTarget(image, gl.TEXTURE_CUBE_MAP, program);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ }
+
+ function runTestOnBindingTarget(image, bindingTarget, program) {
+ var cases = [
+ { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor },
+ { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor },
+ { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor },
+ { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor },
+ ];
+ for (var i in cases) {
+ runOneIteration(image, cases[i].sub, cases[i].flipY,
+ cases[i].topColor, cases[i].bottomColor,
+ bindingTarget, program);
+ }
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js
new file mode 100644
index 000000000..2d0103059
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js
@@ -0,0 +1,299 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This block needs to be outside the onload handler in order for this
+// test to run reliably in WebKit's test harness (at least the
+// Chromium port). https://bugs.webkit.org/show_bug.cgi?id=87448
+initTestingHarness();
+
+var old = debug;
+var debug = function(msg) {
+ bufferedLogToConsole(msg);
+ old(msg);
+};
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ // Test each format separately because many browsers implement each
+ // differently. Some might be GPU accelerated, some might not. Etc...
+ var videos = [
+ { src: resourcePath + "red-green.mp4" , type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', },
+ { src: resourcePath + "red-green.webmvp8.webm", type: 'video/webm; codecs="vp8, vorbis"', },
+ { src: resourcePath + "red-green.webmvp9.webm", type: 'video/webm; codecs="vp9"', },
+ { src: resourcePath + "red-green.theora.ogv", type: 'video/ogg; codecs="theora, vorbis"', },
+ ];
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking video elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ runTest();
+ }
+
+ function runOneIteration(videoElement, useTexSubImage2D, flipY, topColor, bottomColor, sourceSubRectangle, program, bindingTarget)
+ {
+ sourceSubRectangleString = '';
+ if (sourceSubRectangle) {
+ sourceSubRectangleString = ' sourceSubRectangle=' + sourceSubRectangle;
+ }
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
+ ' with flipY=' + flipY + ' bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') +
+ sourceSubRectangleString);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ var targets = [gl.TEXTURE_2D];
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ }
+ // Handle the source sub-rectangle if specified (WebGL 2.0 only)
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
+ }
+ // Upload the videoElement into the texture
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (sourceSubRectangle) {
+ // Initialize the texture to black first
+ if (useTexSubImage2D) {
+ // Skip sub-rectangle tests for cube map textures for the moment.
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ continue;
+ }
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ sourceSubRectangle[2], sourceSubRectangle[3], 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0,
+ sourceSubRectangle[2], sourceSubRectangle[3],
+ gl[pixelFormat], gl[pixelType], videoElement);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ sourceSubRectangle[2], sourceSubRectangle[3], 0,
+ gl[pixelFormat], gl[pixelType], videoElement);
+ }
+ } else {
+ // Initialize the texture to black first
+ if (useTexSubImage2D) {
+ var width = videoElement.videoWidth;
+ var height = videoElement.videoHeight;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ // cube map texture must be square.
+ width = Math.max(width, height);
+ height = width;
+ }
+ gl.texImage2D(targets[tt], 0, gl[internalFormat],
+ width, height, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], videoElement);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], videoElement);
+ }
+ }
+ }
+
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ }
+
+ var c = document.createElement("canvas");
+ c.width = 16;
+ c.height = 16;
+ c.style.border = "1px solid black";
+ var ctx = c.getContext("2d");
+ ctx.drawImage(videoElement, 0, 0, 16, 16);
+ document.body.appendChild(c);
+
+ var loc;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ }
+
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ // Check a few pixels near the top and bottom and make sure they have
+ // the right color.
+ var tolerance = 5;
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor,
+ "shouldBe " + bottomColor, tolerance);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor,
+ "shouldBe " + topColor, tolerance);
+ }
+ }
+
+ function runTest(videoElement)
+ {
+ var cases = [
+ { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor },
+ { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor },
+ { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor },
+ { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor },
+ ];
+
+ if (wtu.getDefault3DContextVersion() > 1) {
+ cases = cases.concat([
+ { sub: false, flipY: false, topColor: redColor, bottomColor: redColor,
+ sourceSubRectangle: [20, 16, 40, 32] },
+ { sub: false, flipY: true, topColor: greenColor, bottomColor: greenColor,
+ sourceSubRectangle: [20, 16, 40, 32] },
+ { sub: false, flipY: false, topColor: greenColor, bottomColor: greenColor,
+ sourceSubRectangle: [20, 80, 40, 32] },
+ { sub: false, flipY: true, topColor: redColor, bottomColor: redColor,
+ sourceSubRectangle: [20, 80, 40, 32] },
+ { sub: true, flipY: false, topColor: redColor, bottomColor: redColor,
+ sourceSubRectangle: [20, 16, 40, 32] },
+ { sub: true, flipY: true, topColor: greenColor, bottomColor: greenColor,
+ sourceSubRectangle: [20, 16, 40, 32] },
+ { sub: true, flipY: false, topColor: greenColor, bottomColor: greenColor,
+ sourceSubRectangle: [20, 80, 40, 32] },
+ { sub: true, flipY: true, topColor: redColor, bottomColor: redColor,
+ sourceSubRectangle: [20, 80, 40, 32] },
+ ]);
+ }
+
+ function runTexImageTest(bindingTarget) {
+ var program;
+ if (bindingTarget == gl.TEXTURE_2D) {
+ program = tiu.setupTexturedQuad(gl, internalFormat);
+ } else {
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ }
+
+ return new Promise(function(resolve, reject) {
+ var videoNdx = 0;
+ var video;
+ function runNextVideo() {
+ if (video) {
+ video.pause();
+ }
+
+ if (videoNdx == videos.length) {
+ resolve("SUCCESS");
+ return;
+ }
+
+ var info = videos[videoNdx++];
+ debug("");
+ debug("testing: " + info.type);
+ video = document.createElement("video");
+ var canPlay = true;
+ if (!video.canPlayType) {
+ testFailed("video.canPlayType required method missing");
+ runNextVideo();
+ return;
+ }
+
+ if(!video.canPlayType(info.type).replace(/no/, '')) {
+ debug(info.type + " unsupported");
+ runNextVideo();
+ return;
+ };
+
+ document.body.appendChild(video);
+ video.type = info.type;
+ video.src = info.src;
+ wtu.startPlayingAndWaitForVideo(video, runTest);
+ }
+ function runTest() {
+ for (var i in cases) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ // Cube map texture must be square but video is not square.
+ if (!cases[i].sub) {
+ break;
+ }
+ // Skip sub-rectangle tests for cube map textures for the moment.
+ if (cases[i].sourceSubRectangle) {
+ break;
+ }
+ }
+ runOneIteration(video, cases[i].sub, cases[i].flipY,
+ cases[i].topColor, cases[i].bottomColor,
+ cases[i].sourceSubRectangle,
+ program, bindingTarget);
+ }
+ runNextVideo();
+ }
+ runNextVideo();
+ });
+ }
+
+ runTexImageTest(gl.TEXTURE_2D).then(function(val) {
+ runTexImageTest(gl.TEXTURE_CUBE_MAP).then(function(val) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ });
+ });
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js
new file mode 100644
index 000000000..534965ba3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js
@@ -0,0 +1,249 @@
+/*
+** Copyright (c) 2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ function init()
+ {
+ description('Verify texImage2D and texSubImage2D code paths taking webgl canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ runTest();
+ }
+
+ function setCanvasToRedGreen(ctx) {
+ var width = ctx.canvas.width;
+ var height = ctx.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+
+ ctx.viewport(0, 0, width, height);
+
+ ctx.enable(ctx.SCISSOR_TEST);
+ ctx.scissor(0, 0, width, halfHeight);
+ ctx.clearColor(1.0, 0, 0, 1.0);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.scissor(0, halfHeight, width, height - halfHeight);
+ ctx.clearColor(0.0, 1.0, 0, 1.0);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.disable(ctx.SCISSOR_TEST);
+ }
+
+ function setCanvasTo257x257(ctx, bindingTarget) {
+ ctx.canvas.width = 257;
+ ctx.canvas.height = 257;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function setCanvasToMin(ctx, bindingTarget) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ // cube map texture must be square.
+ ctx.canvas.width = 2;
+ } else {
+ ctx.canvas.width = 1;
+ }
+ ctx.canvas.height = 2;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function runOneIteration(canvas, useTexSubImage2D, flipY, program, bindingTarget, opt_texture)
+ {
+ debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + ' with flipY=' +
+ flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') +
+ ' canvas size: ' + canvas.width + 'x' + canvas.height + ' with red-green');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ if (!opt_texture) {
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ } else {
+ var texture = opt_texture;
+ }
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ var targets = [gl.TEXTURE_2D];
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ }
+ // Upload the image into the texture
+ for (var tt = 0; tt < targets.length; ++tt) {
+ // Initialize the texture to black first
+ if (useTexSubImage2D) {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], canvas.width, canvas.height, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], canvas);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], canvas);
+ }
+ }
+
+ var width = gl.canvas.width;
+ var height = gl.canvas.height;
+ var halfWidth = Math.floor(width / 2);
+ var halfHeight = Math.floor(height / 2);
+ var top = flipY ? (height - halfHeight) : 0;
+ var bottom = flipY ? 0 : (height - halfHeight);
+
+ var loc;
+ var skipCorner = false;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ switch (gl[pixelFormat]) {
+ case gl.RED_INTEGER:
+ case gl.RG_INTEGER:
+ case gl.RGB_INTEGER:
+ case gl.RGBA_INTEGER:
+ // https://github.com/KhronosGroup/WebGL/issues/1819
+ skipCorner = true;
+ break;
+ }
+ }
+
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]);
+
+ // Check the top and bottom halves and make sure they have the right color.
+ debug("Checking " + (flipY ? "top" : "bottom"));
+ wtu.checkCanvasRect(gl, 0, bottom, (skipCorner && !flipY) ? halfWidth : width, halfHeight, redColor,
+ "shouldBe " + redColor);
+ debug("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, 0, top, (skipCorner && flipY) ? halfWidth : width, halfHeight, greenColor,
+ "shouldBe " + greenColor);
+ }
+
+ if (false) {
+ var ma = wtu.makeImageFromCanvas(canvas);
+ document.getElementById("console").appendChild(ma);
+
+ var m = wtu.makeImageFromCanvas(gl.canvas);
+ document.getElementById("console").appendChild(m);
+ document.getElementById("console").appendChild(document.createElement("hr"));
+ }
+
+ return texture;
+ }
+
+ function runTest()
+ {
+ var ctx = wtu.create3DContext();
+ var canvas = ctx.canvas;
+
+ var cases = [
+ { sub: false, flipY: true, init: setCanvasToMin },
+ { sub: false, flipY: false },
+ { sub: true, flipY: true },
+ { sub: true, flipY: false },
+ { sub: false, flipY: true, init: setCanvasTo257x257 },
+ { sub: false, flipY: false },
+ { sub: true, flipY: true },
+ { sub: true, flipY: false },
+ ];
+
+ function runTexImageTest(bindingTarget) {
+ var program;
+ if (bindingTarget == gl.TEXTURE_2D) {
+ program = tiu.setupTexturedQuad(gl, internalFormat);
+ } else {
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ }
+
+ return new Promise(function(resolve, reject) {
+ var count = 4;
+ var caseNdx = 0;
+ var texture = undefined;
+ function runNextTest() {
+ var c = cases[caseNdx];
+ if (c.init) {
+ c.init(ctx, bindingTarget);
+ }
+ texture = runOneIteration(canvas, c.sub, c.flipY, program, bindingTarget, texture);
+ // for the first 2 iterations always make a new texture.
+ if (count > 2) {
+ texture = undefined;
+ }
+ ++caseNdx;
+ if (caseNdx == cases.length) {
+ caseNdx = 0;
+ --count;
+ if (!count) {
+ resolve("SUCCESS");
+ return;
+ }
+ }
+ wtu.waitForComposite(runNextTest);
+ }
+ runNextTest();
+ });
+ }
+
+ runTexImageTest(gl.TEXTURE_2D).then(function(val) {
+ runTexImageTest(gl.TEXTURE_CUBE_MAP).then(function(val) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ });
+ });
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js
new file mode 100644
index 000000000..be7e2cea4
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js
@@ -0,0 +1,304 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var realRedColor = [255, 0, 0];
+ var realGreenColor = [0, 255, 0];
+ var realBlueColor = [0, 0, 255];
+ var realCyanColor = [0, 255, 255];
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+ var blueColor = [0, 0, 255];
+ var cyanColor = [0, 255, 255];
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking a sub-rectangle of a canvas (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ blueColor = [0, 0, 0];
+ cyanColor = [0, 0, 0];
+ break;
+
+ case gl.RG:
+ case gl.RG_INTEGER:
+ blueColor = [0, 0, 0];
+ cyanColor = [0, 255, 0];
+ break;
+
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var canvas2d = document.createElement('canvas');
+ runTest(canvas2d, setupSourceCanvas2D, '2D-rendered canvas');
+
+ var canvasWebGL = document.createElement('canvas');
+ runTest(canvasWebGL, setupSourceCanvasWebGL, 'WebGL-rendered canvas');
+
+ finishTest();
+ }
+
+ function uploadCanvasToTexture(canvas, useTexSubImage3D, flipY, bindingTarget,
+ depth, sourceSubRectangle, unpackImageHeight)
+ {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
+ var uploadWidth = canvas.width;
+ var uploadHeight = canvas.height;
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
+ uploadWidth = sourceSubRectangle[2];
+ uploadHeight = sourceSubRectangle[3];
+ }
+ if (unpackImageHeight) {
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight);
+ }
+ // Upload the image into the texture
+ if (useTexSubImage3D) {
+ // Initialize the texture to black first
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, uploadWidth, uploadHeight, depth,
+ gl[pixelFormat], gl[pixelType], canvas);
+ } else {
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0,
+ gl[pixelFormat], gl[pixelType], canvas);
+ }
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texture upload");
+ }
+
+ function fillStyle2D(ctx, color) {
+ ctx.fillStyle = 'rgb(' + color[0] + ', ' + color[1] + ', ' + color[2] + ')';
+ }
+
+ function setupSourceCanvas2D(canvas) {
+ var width = canvas.width;
+ var height = canvas.height;
+ var halfWidth = Math.floor(width / 2);
+ var halfHeight = Math.floor(height / 2);
+
+ var ctx = canvas.getContext('2d');
+ // Always use the same pattern for this test: four quadrants:
+ // red green
+ // blue cyan
+ // Handle odd-sized canvases
+ fillStyle2D(ctx, realRedColor);
+ ctx.fillRect(0, 0, halfWidth, halfHeight);
+ fillStyle2D(ctx, realGreenColor);
+ ctx.fillRect(halfWidth, 0, width - halfWidth, halfHeight);
+ fillStyle2D(ctx, realBlueColor);
+ ctx.fillRect(0, halfHeight, halfWidth, height - halfHeight);
+ fillStyle2D(ctx, realCyanColor);
+ ctx.fillRect(halfWidth, halfHeight, width - halfWidth, height - halfHeight);
+ }
+
+ function clearColorWebGL(ctx, color) {
+ ctx.clearColor(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0, 1.0);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ }
+
+ function setupSourceCanvasWebGL(canvas) {
+ var width = canvas.width;
+ var height = canvas.height;
+ var halfWidth = Math.floor(width / 2);
+ var halfHeight = Math.floor(height / 2);
+
+ var ctx = canvas.getContext('webgl');
+ // Always use the same pattern for this test: four quadrants:
+ // red green
+ // blue cyan
+ // Handle odd-sized canvases
+
+ ctx.viewport(0, 0, width, height);
+ ctx.enable(ctx.SCISSOR_TEST);
+ // OpenGL origin is lower-left
+ ctx.scissor(0, 0, halfWidth, halfHeight);
+ clearColorWebGL(ctx, realBlueColor);
+ ctx.scissor(halfWidth, 0, width - halfWidth, halfHeight);
+ clearColorWebGL(ctx, realCyanColor);
+ ctx.scissor(0, halfHeight, halfWidth, height - halfHeight);
+ clearColorWebGL(ctx, realRedColor);
+ ctx.scissor(halfWidth, halfHeight, width - halfWidth, height - halfHeight);
+ clearColorWebGL(ctx, realGreenColor);
+ }
+
+ function runOneIteration(canvas, useTexSubImage3D, flipY, bindingTarget,
+ depth, sourceSubRectangle, unpackImageHeight,
+ rTextureCoord, expectedColor, program,
+ canvasSize, canvasSetupFunction, sourceDescription)
+ {
+ debug('');
+ debug('Testing ' + sourceDescription + ' with ' +
+ (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') +
+ ', flipY=' + flipY + ', bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') +
+ ', sourceSubRectangle=' + sourceSubRectangle +
+ ', depth=' + depth +
+ (unpackImageHeight ? ', unpackImageHeight=' + unpackImageHeight : '') +
+ ', rTextureCoord=' + rTextureCoord);
+
+ // Initialize the contents of the source canvas.
+ var width = canvasSize[0];
+ var height = canvasSize[1];
+ var halfWidth = Math.floor(width / 2);
+ var halfHeight = Math.floor(height / 2);
+ canvas.width = width;
+ canvas.height = height;
+ canvasSetupFunction(canvas);
+
+ uploadCanvasToTexture(canvas, useTexSubImage3D, flipY, bindingTarget,
+ depth, sourceSubRectangle, unpackImageHeight);
+ var rCoordLocation = gl.getUniformLocation(program, 'uRCoord');
+ if (!rCoordLocation) {
+ testFailed('Shader incorrectly set up; couldn\'t find uRCoord uniform');
+ return;
+ }
+ gl.uniform1f(rCoordLocation, rTextureCoord);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ // Check the rendered canvas
+ wtu.checkCanvasRect(gl, 0, 0, canvasSize[0], canvasSize[1], expectedColor, "shouldBe " + expectedColor);
+ }
+
+ function runTest(canvas, canvasSetupFunction, sourceDescription)
+ {
+ var cases = [
+ // Small canvas cases. Expected that these won't be
+ // GPU-accelerated in most browsers' implementations.
+
+ // No UNPACK_IMAGE_HEIGHT specified.
+ { expected: redColor, flipY: false, size: [4, 4], subRect: [0, 0, 2, 2], depth: 2, rTextureCoord: 0.0 },
+ { expected: blueColor, flipY: false, size: [4, 4], subRect: [0, 0, 2, 2], depth: 2, rTextureCoord: 1.0 },
+ { expected: blueColor, flipY: true, size: [4, 4], subRect: [0, 0, 2, 2], depth: 2, rTextureCoord: 0.0 },
+ { expected: redColor, flipY: true, size: [4, 4], subRect: [0, 0, 2, 2], depth: 2, rTextureCoord: 1.0 },
+ { expected: greenColor, flipY: false, size: [4, 4], subRect: [2, 0, 2, 2], depth: 2, rTextureCoord: 0.0 },
+ { expected: cyanColor, flipY: false, size: [4, 4], subRect: [2, 0, 2, 2], depth: 2, rTextureCoord: 1.0 },
+ { expected: cyanColor, flipY: true, size: [4, 4], subRect: [2, 0, 2, 2], depth: 2, rTextureCoord: 0.0 },
+ { expected: greenColor, flipY: true, size: [4, 4], subRect: [2, 0, 2, 2], depth: 2, rTextureCoord: 1.0 },
+
+ // Use UNPACK_IMAGE_HEIGHT to skip some pixels.
+ { expected: redColor, flipY: false, size: [4, 4], subRect: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0 },
+ { expected: blueColor, flipY: false, size: [4, 4], subRect: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0 },
+ { expected: blueColor, flipY: true, size: [4, 4], subRect: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0 },
+ { expected: redColor, flipY: true, size: [4, 4], subRect: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0 },
+ { expected: greenColor, flipY: false, size: [4, 4], subRect: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0 },
+ { expected: cyanColor, flipY: false, size: [4, 4], subRect: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0 },
+ { expected: cyanColor, flipY: true, size: [4, 4], subRect: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0 },
+ { expected: greenColor, flipY: true, size: [4, 4], subRect: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0 },
+
+ // Larger canvas cases. Expected that these will be
+ // GPU-accelerated in most browsers' implementations.
+ // Changes will be gladly accepted to trigger more
+ // browsers' heuristics to accelerate these canvases.
+
+ // No UNPACK_IMAGE_HEIGHT specified.
+ { expected: redColor, flipY: false, size: [384, 384], subRect: [0, 0, 192, 192], depth: 2, rTextureCoord: 0.0 },
+ { expected: blueColor, flipY: false, size: [384, 384], subRect: [0, 0, 192, 192], depth: 2, rTextureCoord: 1.0 },
+ { expected: blueColor, flipY: true, size: [384, 384], subRect: [0, 0, 192, 192], depth: 2, rTextureCoord: 0.0 },
+ { expected: redColor, flipY: true, size: [384, 384], subRect: [0, 0, 192, 192], depth: 2, rTextureCoord: 1.0 },
+ { expected: greenColor, flipY: false, size: [384, 384], subRect: [192, 0, 192, 192], depth: 2, rTextureCoord: 0.0 },
+ { expected: cyanColor, flipY: false, size: [384, 384], subRect: [192, 0, 192, 192], depth: 2, rTextureCoord: 1.0 },
+ { expected: cyanColor, flipY: true, size: [384, 384], subRect: [192, 0, 192, 192], depth: 2, rTextureCoord: 0.0 },
+ { expected: greenColor, flipY: true, size: [384, 384], subRect: [192, 0, 192, 192], depth: 2, rTextureCoord: 1.0 },
+
+ // Use UNPACK_IMAGE_HEIGHT to skip some pixels.
+ { expected: redColor, flipY: false, size: [384, 384], subRect: [0, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 0.0 },
+ { expected: blueColor, flipY: false, size: [384, 384], subRect: [0, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 1.0 },
+ { expected: blueColor, flipY: true, size: [384, 384], subRect: [0, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 0.0 },
+ { expected: redColor, flipY: true, size: [384, 384], subRect: [0, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 1.0 },
+ { expected: greenColor, flipY: false, size: [384, 384], subRect: [192, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 0.0 },
+ { expected: cyanColor, flipY: false, size: [384, 384], subRect: [192, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 1.0 },
+ { expected: cyanColor, flipY: true, size: [384, 384], subRect: [192, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 0.0 },
+ { expected: greenColor, flipY: true, size: [384, 384], subRect: [192, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 1.0 },
+ ];
+
+ var program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ for (var i in cases) {
+ runOneIteration(canvas, false, cases[i].flipY, gl.TEXTURE_3D,
+ cases[i].depth, cases[i].subRect,
+ cases[i].unpackImageHeight, cases[i].rTextureCoord,
+ cases[i].expected,
+ program, cases[i].size, canvasSetupFunction, sourceDescription);
+ runOneIteration(canvas, true, cases[i].flipY, gl.TEXTURE_3D,
+ cases[i].depth, cases[i].subRect,
+ cases[i].unpackImageHeight, cases[i].rTextureCoord,
+ cases[i].expected,
+ program, cases[i].size, canvasSetupFunction, sourceDescription);
+ }
+
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ for (var i in cases) {
+ runOneIteration(canvas, false, cases[i].flipY, gl.TEXTURE_2D_ARRAY,
+ cases[i].depth, cases[i].subRect,
+ cases[i].unpackImageHeight, cases[i].rTextureCoord,
+ cases[i].expected,
+ program, cases[i].size, canvasSetupFunction, sourceDescription);
+ runOneIteration(canvas, true, cases[i].flipY, gl.TEXTURE_2D_ARRAY,
+ cases[i].depth, cases[i].subRect,
+ cases[i].unpackImageHeight, cases[i].rTextureCoord,
+ cases[i].expected,
+ program, cases[i].size, canvasSetupFunction, sourceDescription);
+ }
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js
new file mode 100644
index 000000000..c577d0f44
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js
@@ -0,0 +1,233 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var whiteColor = [255, 255, 255, 255];
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ whiteColor = [255, 0, 0, 255];
+ greenColor = [0, 0, 0];
+ break;
+ case gl.RG:
+ case gl.RG_INTEGER:
+ whiteColor = [255, 255, 0, 255];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var testCanvas = document.createElement('canvas');
+ runTest(testCanvas);
+ //document.body.appendChild(testCanvas);
+ }
+
+ function setCanvasToRedGreen(ctx) {
+ var width = ctx.canvas.width;
+ var height = ctx.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ ctx.fillStyle = "#ff0000";
+ ctx.fillRect(0, 0, width, halfHeight);
+ ctx.fillStyle = "#00ff00";
+ ctx.fillRect(0, halfHeight, width, height - halfHeight);
+ }
+
+ function drawTextInCanvas(ctx, bindingTarget) {
+ var width = ctx.canvas.width;
+ var height = ctx.canvas.height;
+ ctx.fillStyle = "#ffffff";
+ ctx.fillRect(0, 0, width, height);
+ ctx.font = '20pt Arial';
+ ctx.fillStyle = 'black';
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.fillText("1234567890", width / 2, height / 4);
+ }
+
+ function setCanvasTo257x257(ctx, bindingTarget) {
+ ctx.canvas.width = 257;
+ ctx.canvas.height = 257;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function setCanvasToMin(ctx, bindingTarget) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ // cube map texture must be square.
+ ctx.canvas.width = 2;
+ } else {
+ ctx.canvas.width = 1;
+ }
+ ctx.canvas.height = 2;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function runOneIteration(canvas, flipY, program, bindingTarget, opt_texture, opt_fontTest)
+ {
+ debug('Testing ' + ' with flipY=' + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') +
+ ' canvas size: ' + canvas.width + 'x' + canvas.height + (opt_fontTest ? " with fonts" : " with red-green"));
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ if (!opt_texture) {
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ } else {
+ var texture = opt_texture;
+ }
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ // Initialize the texture to black first
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], canvas.width, canvas.height, 1 /* depth */, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, canvas.width, canvas.height, 1 /* depth */,
+ gl[pixelFormat], gl[pixelType], canvas);
+
+ var width = gl.canvas.width;
+ var height = gl.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ var top = flipY ? 0 : (height - halfHeight);
+ var bottom = flipY ? (height - halfHeight) : 0;
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]);
+
+ if (opt_fontTest) {
+ // check half is a solid color.
+ wtu.checkCanvasRect(
+ gl, 0, top, width, halfHeight,
+ whiteColor,
+ "should be white");
+ // check other half is not a solid color.
+ wtu.checkCanvasRectColor(
+ gl, 0, bottom, width, halfHeight,
+ whiteColor, 0,
+ function() {
+ testFailed("font missing");
+ },
+ function() {
+ testPassed("font renderered");
+ },
+ debug);
+ } else {
+ // Check the top and bottom halves and make sure they have the right color.
+ debug("Checking " + (flipY ? "top" : "bottom"));
+ wtu.checkCanvasRect(gl, 0, bottom, width, halfHeight, redColor,
+ "shouldBe " + redColor);
+ debug("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, 0, top, width, halfHeight, greenColor,
+ "shouldBe " + greenColor);
+ }
+
+ return texture;
+ }
+
+ function runTest(canvas)
+ {
+ var ctx = canvas.getContext("2d");
+
+ var cases = [
+ { flipY: true, font: false, init: setCanvasToMin },
+ { flipY: false, font: false },
+ { flipY: true, font: false, init: setCanvasTo257x257 },
+ { flipY: false, font: false },
+ { flipY: true, font: true, init: drawTextInCanvas },
+ { flipY: false, font: true },
+ ];
+
+ function runTexImageTest(bindingTarget) {
+ var program;
+ if (bindingTarget == gl.TEXTURE_3D) {
+ program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ } else { // TEXTURE_2D_ARRAY
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ }
+
+ return new Promise(function(resolve, reject) {
+ var count = 4;
+ var caseNdx = 0;
+ var texture = undefined;
+ function runNextTest() {
+ var c = cases[caseNdx];
+ if (c.init) {
+ c.init(ctx, bindingTarget);
+ }
+ texture = runOneIteration(canvas, c.flipY, program, bindingTarget, texture, c.font);
+ // for the first 2 iterations always make a new texture.
+ if (count > 2) {
+ texture = undefined;
+ }
+ ++caseNdx;
+ if (caseNdx == cases.length) {
+ caseNdx = 0;
+ --count;
+ if (!count) {
+ resolve("SUCCESS");
+ return;
+ }
+ }
+ wtu.waitForComposite(runNextTest);
+ }
+ runNextTest();
+ });
+ }
+
+ runTexImageTest(gl.TEXTURE_3D).then(function(val) {
+ runTexImageTest(gl.TEXTURE_2D_ARRAY).then(function(val) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ });
+ });
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js
new file mode 100644
index 000000000..1dab09bfa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js
@@ -0,0 +1,63 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from a Blob (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", resourcePath + "red-green-semi-transparent.png");
+ xhr.responseType = 'blob';
+ xhr.send();
+ xhr.onload = function() {
+ var blob = xhr.response;
+ runImageBitmapTest(blob, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ finishTest();
+ }
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js
new file mode 100644
index 000000000..fb7d5e6ed
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js
@@ -0,0 +1,89 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from an HTMLCanvasElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var testCanvas = document.createElement('canvas');
+ var ctx = testCanvas.getContext("2d");
+ setCanvasToMin(ctx);
+ runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+
+ setCanvasTo257x257(ctx);
+ runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ finishTest();
+ }
+
+ function setCanvasToRedGreen(ctx) {
+ var width = ctx.canvas.width;
+ var halfWidth = Math.floor(width / 2);
+ var height = ctx.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ ctx.fillStyle = "rgba(255, 0, 0, 1)";
+ ctx.fillRect(0, 0, halfWidth, halfHeight);
+ ctx.fillStyle = "rgba(255, 0, 0, 0.5)";
+ ctx.fillRect(halfWidth, 0, halfWidth, halfHeight);
+ ctx.fillStyle = "rgba(0, 255, 0, 1)";
+ ctx.fillRect(0, halfHeight, halfWidth, halfHeight);
+ ctx.fillStyle = "rgba(0, 255, 0, 0.5)";
+ ctx.fillRect(halfWidth, halfHeight, halfWidth, halfHeight);
+ }
+
+ function setCanvasToMin(ctx) {
+ ctx.canvas.width = 2;
+ ctx.canvas.height = 2;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function setCanvasTo257x257(ctx) {
+ ctx.canvas.width = 257;
+ ctx.canvas.height = 257;
+ setCanvasToRedGreen(ctx);
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js
new file mode 100644
index 000000000..ba715426f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js
@@ -0,0 +1,67 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from an ImageBitmap (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ var imageData = new ImageData(new Uint8ClampedArray(
+ [255, 0, 0, 255,
+ 255, 0, 0, 0,
+ 0, 255, 0, 255,
+ 0, 255, 0, 0]),
+ 2, 2);
+
+ createImageBitmap(imageData, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(bitmap) {
+ // bitmap is in unpremultiplied form
+ runImageBitmapTest(bitmap, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ finishTest();
+ });
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js
new file mode 100644
index 000000000..71411657b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js
@@ -0,0 +1,64 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ var imageData = new ImageData(new Uint8ClampedArray(
+ [255, 0, 0, 255,
+ 255, 0, 0, 0,
+ 0, 255, 0, 255,
+ 0, 255, 0, 0]),
+ 2, 2);
+
+ runImageBitmapTest(imageData, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ finishTest();
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js
new file mode 100644
index 000000000..2574becd1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js
@@ -0,0 +1,60 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from an HTMLImageElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ var image = new Image();
+ image.onload = function() {
+ runImageBitmapTest(image, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ finishTest();
+ }
+ image.src = resourcePath + "red-green-semi-transparent.png";
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js
new file mode 100644
index 000000000..e385ff90a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js
@@ -0,0 +1,61 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from an HTMLVideoElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ if(!window.createImageBitmap || !window.ImageBitmap) {
+ finishTest();
+ return;
+ }
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ video = document.createElement("video");
+ video.oncanplaythrough = function() {
+ runImageBitmapTest(video, 1, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true);
+ finishTest();
+ }
+ video.src = resourcePath + "red-green.theora.ogv";
+ document.body.appendChild(video);
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js
new file mode 100644
index 000000000..e1368275d
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js
@@ -0,0 +1,276 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var imageData = null;
+ var blackColor = [0, 0, 0];
+ var originalPixels = (function() {
+ // (red|green|blue|cyan)(opaque|transparent)
+ var ro = [255, 0, 0, 255]; var rt = [255, 0, 0, 0];
+ var go = [0, 255, 0, 255]; var gt = [0, 255, 0, 0];
+ var bo = [0, 0, 255, 255]; var bt = [0, 0, 255, 0];
+ var co = [0, 255, 255, 255]; var ct = [0, 255, 255, 0];
+ return [ro, rt, go, gt,
+ ro, rt, go, gt,
+ bo, bt, co, ct,
+ bo, bt, co, ct];
+ })();
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+ gl.disable(gl.BLEND);
+
+ var canvas2d = document.getElementById("texcanvas");
+ var context2d = canvas2d.getContext("2d");
+ imageData = context2d.createImageData(4, 4);
+ var data = imageData.data;
+ for (var i = 0; i < originalPixels.length; i++) {
+ data.set(originalPixels[i], 4 * i);
+ }
+
+ runTest();
+ }
+
+ function runOneIteration(useTexSubImage3D, flipY, premultiplyAlpha, bindingTarget,
+ depth, sourceSubRectangle, rTexCoord, program)
+ {
+ var expected = simulate(flipY, premultiplyAlpha, depth, sourceSubRectangle, rTexCoord);
+ var sourceSubRectangleString = '';
+ if (sourceSubRectangle) {
+ sourceSubRectangleString = ', sourceSubRectangle=' + sourceSubRectangle;
+ sourceSubRectangleString += ', rTexCoord=' + rTexCoord;
+ }
+ debug('');
+ debug('Testing ' + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') +
+ ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha +
+ ', bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') +
+ sourceSubRectangleString);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Enable writes to the RGBA channels
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
+ gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
+ var uploadWidth = imageData.width;
+ var uploadHeight = imageData.height;
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
+ uploadWidth = sourceSubRectangle[2];
+ uploadHeight = sourceSubRectangle[3];
+ }
+ // Upload the image into the texture
+ if (useTexSubImage3D) {
+ // Initialize the texture to black first
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, uploadWidth, uploadHeight, depth,
+ gl[pixelFormat], gl[pixelType], imageData);
+ } else {
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0,
+ gl[pixelFormat], gl[pixelType], imageData);
+ }
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texture upload");
+
+ var tl = expected[0][0];
+ var tr = expected[0][1];
+ var bl = expected[1][0];
+ var br = expected[1][1];
+
+ var rCoordLocation = gl.getUniformLocation(program, 'uRCoord');
+ if (!rCoordLocation) {
+ testFailed("Shader incorrectly set up; couldn't find uRCoord uniform");
+ return;
+ }
+ gl.uniform1f(rCoordLocation, rTexCoord);
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+
+ var width = gl.canvas.width;
+ var halfWidth = Math.floor(width / 2);
+ var height = gl.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+
+ var top = 0;
+ var bottom = height - halfHeight;
+ var left = 0;
+ var right = width - halfWidth;
+
+ debug("Checking pixel values");
+ debug("Expecting: " + expected);
+ var expectedH = expected.length;
+ var expectedW = expected[0].length;
+ var texelH = Math.floor(gl.canvas.height / expectedH);
+ var texelW = Math.floor(gl.canvas.width / expectedW);
+ // For each entry of the expected[][] array, check the appropriate
+ // canvas rectangle for correctness.
+ for (var row = 0; row < expectedH; row++) {
+ var y = row * texelH;
+ for (var col = 0; col < expectedW; col++) {
+ var x = col * texelW;
+ var val = expected[row][col];
+ wtu.checkCanvasRect(gl, x, y, texelW, texelH, val, "should be " + val);
+ }
+ }
+ }
+
+ function runTest()
+ {
+ var program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ runTestOnBindingTarget(gl.TEXTURE_3D, program);
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ runTestOnBindingTarget(gl.TEXTURE_2D_ARRAY, program);
+
+ debug("");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ }
+
+ function simulate(flipY, premultiplyAlpha, depth, sourceSubRectangle, rTexCoord) {
+ var ro = [255, 0, 0]; var rt = premultiplyAlpha ? [0, 0, 0] : [255, 0, 0];
+ var go = [0, 255, 0]; var gt = premultiplyAlpha ? [0, 0, 0] : [0, 255, 0];
+ var bo = [0, 0, 255]; var bt = premultiplyAlpha ? [0, 0, 0] : [0, 0, 255];
+ var co = [0, 255, 255]; var ct = premultiplyAlpha ? [0, 0, 0] : [0, 255, 255];
+ var expected = [[ro, rt, go, gt],
+ [ro, rt, go, gt],
+ [bo, bt, co, ct],
+ [bo, bt, co, ct]];
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ for (var row = 0; row < 4; row++) {
+ for (var col = 0; col < 4; col++) {
+ expected[row][col][1] = 0; // zero the green channel
+ }
+ }
+ // fall-through
+ case gl.RG:
+ case gl.RG_INTEGER:
+ for (var row = 0; row < 4; row++) {
+ for (var col = 0; col < 4; col++) {
+ expected[row][col][2] = 0; // zero the blue channel
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (flipY) {
+ expected.reverse();
+ }
+
+ if (sourceSubRectangle) {
+ let expected2 = [];
+ for (var row = 0; row < sourceSubRectangle[3]; row++) {
+ expected2[row] = [];
+ for (var col = 0; col < sourceSubRectangle[2]; col++) {
+ expected2[row][col] =
+ expected[sourceSubRectangle[1] + row + rTexCoord * sourceSubRectangle[3]][sourceSubRectangle[0] + col];
+ }
+ }
+ expected = expected2;
+ }
+
+ return expected;
+ }
+
+ function runTestOnBindingTarget(bindingTarget, program) {
+ var rects = [
+ undefined,
+ [0, 0, 2, 2],
+ [2, 0, 2, 2],
+ ];
+ var dbg = false; // Set to true for debug output images
+ if (dbg) {
+ (function() {
+ debug("");
+ debug("Original ImageData (transparent pixels appear black):");
+ var cvs = document.createElement("canvas");
+ cvs.width = 4;
+ cvs.height = 4;
+ cvs.style.width = "32px";
+ cvs.style.height = "32px";
+ cvs.style.imageRendering = "pixelated";
+ cvs.style.background = "#000";
+ var ctx = cvs.getContext("2d");
+ ctx.putImageData(imageData, 0, 0);
+ var output = document.getElementById("console");
+ output.appendChild(cvs);
+ })();
+ }
+ for (const sub of [false, true]) {
+ for (const flipY of [false, true]) {
+ for (const premul of [false, true]) {
+ for (let irect = 0; irect < rects.length; irect++) {
+ var rect = rects[irect];
+ let depth = rect ? 2 : 1;
+ for (let rTexCoord = 0; rTexCoord < depth; rTexCoord++) {
+ // TODO: add tests for UNPACK_IMAGE_HEIGHT.
+ runOneIteration(sub, flipY, premul, bindingTarget,
+ depth, rect, rTexCoord, program);
+ if (dbg) {
+ debug("Actual:");
+ var img = document.createElement("img");
+ img.src = gl.canvas.toDataURL("image/png");
+ var output = document.getElementById("console");
+ output.appendChild(img);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js
new file mode 100644
index 000000000..eb7bb6a00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js
@@ -0,0 +1,277 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var imgCanvas;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+ var blueColor = [0, 0, 255];
+ var cyanColor = [0, 255, 255];
+ var imageURLs = [resourcePath + "red-green.png",
+ resourcePath + "red-green-blue-cyan-4x4.png"];
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking image elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ blueColor = [0, 0, 0];
+ cyanColor = [0, 0, 0];
+ break;
+
+ case gl.RG:
+ case gl.RG_INTEGER:
+ blueColor = [0, 0, 0];
+ cyanColor = [0, 255, 0];
+ break;
+
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ wtu.loadImagesAsync(imageURLs, runTest);
+ }
+
+ function uploadImageToTexture(image, useTexSubImage3D, flipY, bindingTarget,
+ depth, sourceSubRectangle, unpackImageHeight)
+ {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
+ var uploadWidth = image.width;
+ var uploadHeight = image.height;
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
+ uploadWidth = sourceSubRectangle[2];
+ uploadHeight = sourceSubRectangle[3];
+ }
+ if (unpackImageHeight) {
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight);
+ }
+ // Upload the image into the texture
+ if (useTexSubImage3D) {
+ // Initialize the texture to black first
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, uploadWidth, uploadHeight, depth,
+ gl[pixelFormat], gl[pixelType], image);
+ } else {
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0,
+ gl[pixelFormat], gl[pixelType], image);
+ }
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texture upload");
+ }
+
+ function runRedGreenTest(image) {
+ function runOneIteration(image, useTexSubImage3D, flipY, bindingTarget, topColor, bottomColor, program)
+ {
+ debug('Testing ' + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') +
+ ' with flipY=' + flipY + ' bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY'));
+
+ uploadImageToTexture(image, useTexSubImage3D, flipY, bindingTarget, 1);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ // Check a few pixels near the top and bottom and make sure they have
+ // the right color.
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor,
+ "shouldBe " + bottomColor);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor,
+ "shouldBe " + topColor);
+ }
+
+ var cases = [
+ { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor },
+ { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor },
+ { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor },
+ { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor },
+ ];
+
+ var program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ for (var i in cases) {
+ runOneIteration(image, cases[i].sub, cases[i].flipY, gl.TEXTURE_3D,
+ cases[i].topColor, cases[i].bottomColor, program);
+ }
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ for (var i in cases) {
+ runOneIteration(image, cases[i].sub, cases[i].flipY, gl.TEXTURE_2D_ARRAY,
+ cases[i].topColor, cases[i].bottomColor, program);
+ }
+ }
+
+ function runRedGreenBlueCyanTest(image) {
+ function runOneIteration(image, useTexSubImage3D, flipY, bindingTarget,
+ depth, sourceSubRectangle, unpackImageHeight,
+ rTextureCoord, topColor, bottomColor, program)
+ {
+ sourceSubRectangleString = '';
+ if (sourceSubRectangle) {
+ sourceSubRectangleString = ' sourceSubRectangle=' + sourceSubRectangle;
+ }
+ unpackImageHeightString = '';
+ if (unpackImageHeight) {
+ unpackImageHeightString = ' unpackImageHeight=' + unpackImageHeight;
+ }
+ debug('Testing ' + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') +
+ ' with flipY=' + flipY + ' bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') +
+ sourceSubRectangleString + ' depth=' + depth + unpackImageHeightString +
+ ' rTextureCoord=' + rTextureCoord);
+
+ uploadImageToTexture(image, useTexSubImage3D, flipY, bindingTarget,
+ depth, sourceSubRectangle, unpackImageHeight);
+ var rCoordLocation = gl.getUniformLocation(program, 'uRCoord');
+ if (!rCoordLocation) {
+ testFailed('Shader incorrectly set up; couldn\'t find uRCoord uniform');
+ return;
+ }
+ gl.uniform1f(rCoordLocation, rTextureCoord);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ // Check a few pixels near the top and bottom and make sure they have
+ // the right color.
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor,
+ "shouldBe " + bottomColor);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor,
+ "shouldBe " + topColor);
+ }
+
+ var cases = [
+ // No UNPACK_IMAGE_HEIGHT specified.
+ { flipY: false, sourceSubRectangle: [0, 0, 2, 2], depth: 2, rTextureCoord: 0.0,
+ topColor: redColor, bottomColor: redColor },
+ { flipY: false, sourceSubRectangle: [0, 0, 2, 2], depth: 2, rTextureCoord: 1.0,
+ topColor: blueColor, bottomColor: blueColor },
+ { flipY: true, sourceSubRectangle: [0, 0, 2, 2], depth: 2, rTextureCoord: 0.0,
+ topColor: blueColor, bottomColor: blueColor },
+ { flipY: true, sourceSubRectangle: [0, 0, 2, 2], depth: 2, rTextureCoord: 1.0,
+ topColor: redColor, bottomColor: redColor },
+ { flipY: false, sourceSubRectangle: [2, 0, 2, 2], depth: 2, rTextureCoord: 0.0,
+ topColor: greenColor, bottomColor: greenColor },
+ { flipY: false, sourceSubRectangle: [2, 0, 2, 2], depth: 2, rTextureCoord: 1.0,
+ topColor: cyanColor, bottomColor: cyanColor },
+ { flipY: true, sourceSubRectangle: [2, 0, 2, 2], depth: 2, rTextureCoord: 0.0,
+ topColor: cyanColor, bottomColor: cyanColor },
+ { flipY: true, sourceSubRectangle: [2, 0, 2, 2], depth: 2, rTextureCoord: 1.0,
+ topColor: greenColor, bottomColor: greenColor },
+
+ // Use UNPACK_IMAGE_HEIGHT to skip some pixels.
+ { flipY: false, sourceSubRectangle: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0,
+ topColor: redColor, bottomColor: redColor },
+ { flipY: false, sourceSubRectangle: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0,
+ topColor: blueColor, bottomColor: blueColor },
+ { flipY: true, sourceSubRectangle: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0,
+ topColor: blueColor, bottomColor: blueColor },
+ { flipY: true, sourceSubRectangle: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0,
+ topColor: redColor, bottomColor: redColor },
+ { flipY: false, sourceSubRectangle: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0,
+ topColor: greenColor, bottomColor: greenColor },
+ { flipY: false, sourceSubRectangle: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0,
+ topColor: cyanColor, bottomColor: cyanColor },
+ { flipY: true, sourceSubRectangle: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0,
+ topColor: cyanColor, bottomColor: cyanColor },
+ { flipY: true, sourceSubRectangle: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0,
+ topColor: greenColor, bottomColor: greenColor },
+ ];
+
+ var program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ for (var i in cases) {
+ runOneIteration(image, false, cases[i].flipY, gl.TEXTURE_3D,
+ cases[i].depth, cases[i].sourceSubRectangle,
+ cases[i].unpackImageHeight, cases[i].rTextureCoord,
+ cases[i].topColor, cases[i].bottomColor,
+ program);
+ runOneIteration(image, true, cases[i].flipY, gl.TEXTURE_3D,
+ cases[i].depth, cases[i].sourceSubRectangle,
+ cases[i].unpackImageHeight, cases[i].rTextureCoord,
+ cases[i].topColor, cases[i].bottomColor,
+ program);
+ }
+
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ for (var i in cases) {
+ runOneIteration(image, false, cases[i].flipY, gl.TEXTURE_2D_ARRAY,
+ cases[i].depth, cases[i].sourceSubRectangle,
+ cases[i].unpackImageHeight, cases[i].rTextureCoord,
+ cases[i].topColor, cases[i].bottomColor,
+ program);
+ runOneIteration(image, true, cases[i].flipY, gl.TEXTURE_2D_ARRAY,
+ cases[i].depth, cases[i].sourceSubRectangle,
+ cases[i].unpackImageHeight, cases[i].rTextureCoord,
+ cases[i].topColor, cases[i].bottomColor,
+ program);
+ }
+ }
+
+ function runTest(imageMap)
+ {
+ runRedGreenTest(imageMap[imageURLs[0]]);
+ runRedGreenBlueCyanTest(imageMap[imageURLs[1]]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js
new file mode 100644
index 000000000..c940a601a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js
@@ -0,0 +1,121 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var imgCanvas;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking SVG image elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ wtu.loadTexture(gl, resourcePath + "red-green.svg", runTest);
+ }
+
+ function runOneIteration(image, flipY, topColor, bottomColor, bindingTarget, program)
+ {
+ debug('Testing ' + ' with flipY=' + flipY + ' bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY'));
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+ // Upload the image into the texture
+ // Initialize the texture to black first
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], image.width, image.height, 1 /* depth */, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, image.width, image.height, 1 /* depth */,
+ gl[pixelFormat], gl[pixelType], image);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ // Check a few pixels near the top and bottom and make sure they have
+ // the right color.
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor,
+ "shouldBe " + bottomColor);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor,
+ "shouldBe " + topColor);
+ }
+
+ function runTest(image)
+ {
+ var program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ runTestOnBindingTarget(image, gl.TEXTURE_3D, program);
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ runTestOnBindingTarget(image, gl.TEXTURE_2D_ARRAY, program);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ }
+
+ function runTestOnBindingTarget(image, bindingTarget, program) {
+ var cases = [
+ { flipY: true, topColor: redColor, bottomColor: greenColor },
+ { flipY: false, topColor: greenColor, bottomColor: redColor },
+ ];
+ for (var i in cases) {
+ runOneIteration(image, cases[i].flipY,
+ cases[i].topColor, cases[i].bottomColor,
+ bindingTarget, program);
+ }
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js
new file mode 100644
index 000000000..3495bf17f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js
@@ -0,0 +1,260 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This block needs to be outside the onload handler in order for this
+// test to run reliably in WebKit's test harness (at least the
+// Chromium port). https://bugs.webkit.org/show_bug.cgi?id=87448
+initTestingHarness();
+
+var old = debug;
+var debug = function(msg) {
+ bufferedLogToConsole(msg);
+ old(msg);
+};
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ // Test each format separately because many browsers implement each
+ // differently. Some might be GPU accelerated, some might not. Etc...
+ var videos = [
+ { src: resourcePath + "red-green.mp4" , type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', },
+ { src: resourcePath + "red-green.webmvp9.webm", type: 'video/webm; codecs="vp9"', },
+ { src: resourcePath + "red-green.webmvp8.webm", type: 'video/webm; codecs="vp8, vorbis"', },
+ { src: resourcePath + "red-green.theora.ogv", type: 'video/ogg; codecs="theora, vorbis"', },
+ ];
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking video elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ runTest();
+ }
+
+ function runOneIteration(videoElement, flipY, useTexSubImage3D, topColor, bottomColor, program, bindingTarget,
+ depth, sourceSubRectangle, unpackImageHeight, rTextureCoord)
+ {
+ debug('Testing ' +
+ (useTexSubImage3D ? "texSubImage3D" : "texImage3D") +
+ ' with flipY=' + flipY + ' bindingTarget=' +
+ (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') +
+ (sourceSubRectangle ? ', sourceSubRectangle=' + sourceSubRectangle : '') +
+ (unpackImageHeight ? ', unpackImageHeight=' + unpackImageHeight : '') +
+ ', depth=' + depth +
+ ', rTextureCoord=' + rTextureCoord);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Disable any writes to the alpha channel
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
+ var uploadWidth = videoElement.width;
+ var uploadHeight = videoElement.height;
+ if (sourceSubRectangle) {
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
+ uploadWidth = sourceSubRectangle[2];
+ uploadHeight = sourceSubRectangle[3];
+ }
+ if (unpackImageHeight) {
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight);
+ }
+ // Upload the videoElement into the texture
+ if (useTexSubImage3D) {
+ // Initialize the texture to black first
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat],
+ uploadWidth, uploadHeight, depth, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage3D(bindingTarget, 0, 0, 0, 0,
+ uploadWidth, uploadHeight, depth,
+ gl[pixelFormat], gl[pixelType], videoElement);
+ } else {
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat],
+ uploadWidth, uploadHeight, depth, 0,
+ gl[pixelFormat], gl[pixelType], videoElement);
+ }
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0);
+
+ var c = document.createElement("canvas");
+ c.width = 16;
+ c.height = 16;
+ c.style.border = "1px solid black";
+ var ctx = c.getContext("2d");
+ ctx.drawImage(videoElement, 0, 0, 16, 16);
+ document.body.appendChild(c);
+
+ var rCoordLocation = gl.getUniformLocation(program, 'uRCoord');
+ if (!rCoordLocation) {
+ testFailed('Shader incorrectly set up; couldn\'t find uRCoord uniform');
+ return;
+ }
+ gl.uniform1f(rCoordLocation, rTextureCoord);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+ // Check a few pixels near the top and bottom and make sure they have
+ // the right color.
+ var tolerance = 5;
+ debug("Checking lower left corner");
+ wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor,
+ "shouldBe " + bottomColor, tolerance);
+ debug("Checking upper left corner");
+ wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor,
+ "shouldBe " + topColor, tolerance);
+ }
+
+ function runTest(videoElement)
+ {
+ var cases = [
+ // No UNPACK_IMAGE_HEIGHT specified.
+ { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 5, rTextureCoord: 0,
+ topColor: redColor, bottomColor: redColor },
+ // Note that an rTextureCoord of 4.0 satisfies the need to
+ // have it be >= 1.0 for the TEXTURE_3D case, and also its
+ // use as an index in the TEXTURE_2D_ARRAY case.
+ { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 5, rTextureCoord: 4,
+ topColor: greenColor, bottomColor: greenColor },
+ { flipY: false, sourceSubRectangle: [24, 48, 32, 32], depth: 1, rTextureCoord: 0,
+ topColor: greenColor, bottomColor: redColor },
+ { flipY: true, sourceSubRectangle: [24, 48, 32, 32], depth: 1, rTextureCoord: 0,
+ topColor: redColor, bottomColor: greenColor },
+
+ // Use UNPACK_IMAGE_HEIGHT to skip some pixels.
+ { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 2, unpackImageHeight: 64, rTextureCoord: 0,
+ topColor: redColor, bottomColor: redColor },
+ { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 2, unpackImageHeight: 64, rTextureCoord: 1,
+ topColor: greenColor, bottomColor: greenColor },
+ ];
+
+ function runTexImageTest(bindingTarget) {
+ var program;
+ if (bindingTarget == gl.TEXTURE_3D) {
+ program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ } else {
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ }
+
+ return new Promise(function(resolve, reject) {
+ var videoNdx = 0;
+ var video;
+ function runNextVideo() {
+ if (video) {
+ video.pause();
+ }
+
+ if (videoNdx == videos.length) {
+ resolve("SUCCESS");
+ return;
+ }
+
+ var info = videos[videoNdx++];
+ debug("");
+ debug("testing: " + info.type);
+ video = document.createElement("video");
+ var canPlay = true;
+ if (!video.canPlayType) {
+ testFailed("video.canPlayType required method missing");
+ runNextVideo();
+ return;
+ }
+
+ if(!video.canPlayType(info.type).replace(/no/, '')) {
+ debug(info.type + " unsupported");
+ runNextVideo();
+ return;
+ };
+
+ document.body.appendChild(video);
+ video.type = info.type;
+ video.src = info.src;
+ wtu.startPlayingAndWaitForVideo(video, runTest);
+ }
+ function runTest() {
+ for (var i in cases) {
+ runOneIteration(video, cases[i].flipY, false,
+ cases[i].topColor, cases[i].bottomColor,
+ program, bindingTarget, cases[i].depth,
+ cases[i].sourceSubRectangle,
+ cases[i].unpackImageHeight,
+ cases[i].rTextureCoord);
+ runOneIteration(video, cases[i].flipY, true,
+ cases[i].topColor, cases[i].bottomColor,
+ program, bindingTarget, cases[i].depth,
+ cases[i].sourceSubRectangle,
+ cases[i].unpackImageHeight,
+ cases[i].rTextureCoord);
+ }
+ runNextVideo();
+ }
+ runNextVideo();
+ });
+ }
+
+ runTexImageTest(gl.TEXTURE_3D).then(function(val) {
+ runTexImageTest(gl.TEXTURE_2D_ARRAY).then(function(val) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ });
+ });
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js
new file mode 100644
index 000000000..f9415cf85
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js
@@ -0,0 +1,204 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
+ var wtu = WebGLTestUtils;
+ var tiu = TexImageUtils;
+ var gl = null;
+ var successfullyParsed = false;
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+
+ function init()
+ {
+ description('Verify texImage3D and texSubImage3D code paths taking webgl canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
+
+ // Set the default context version while still allowing the webglVersion URL query string to override it.
+ wtu.setDefault3DContextVersion(defaultContextVersion);
+ gl = wtu.create3DContext("example");
+
+ if (!prologue(gl)) {
+ finishTest();
+ return;
+ }
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ gl.clearColor(0,0,0,1);
+ gl.clearDepth(1);
+
+ runTest();
+ }
+
+ function setCanvasToRedGreen(ctx) {
+ var width = ctx.canvas.width;
+ var height = ctx.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+
+ ctx.viewport(0, 0, width, height);
+
+ ctx.enable(ctx.SCISSOR_TEST);
+ ctx.scissor(0, 0, width, halfHeight);
+ ctx.clearColor(1.0, 0, 0, 1.0);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.scissor(0, halfHeight, width, height - halfHeight);
+ ctx.clearColor(0.0, 1.0, 0, 1.0);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.disable(ctx.SCISSOR_TEST);
+ }
+
+ function setCanvasTo257x257(ctx, bindingTarget) {
+ ctx.canvas.width = 257;
+ ctx.canvas.height = 257;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function setCanvasToMin(ctx, bindingTarget) {
+ ctx.canvas.width = 1;
+ ctx.canvas.height = 2;
+ setCanvasToRedGreen(ctx);
+ }
+
+ function runOneIteration(canvas, flipY, program, bindingTarget, opt_texture)
+ {
+ debug('Testing ' + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') +
+ ' canvas size: ' + canvas.width + 'x' + canvas.height + ' with red-green');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ if (!opt_texture) {
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ } else {
+ var texture = opt_texture;
+ }
+ // Set up pixel store parameters
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+ wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
+
+ // Upload the image into the texture
+ // Initialize the texture to black first
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], canvas.width, canvas.height, 1 /* depth */, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, canvas.width, canvas.height, 1 /* depth */,
+ gl[pixelFormat], gl[pixelType], canvas);
+
+ var width = gl.canvas.width;
+ var height = gl.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ var top = flipY ? (height - halfHeight) : 0;
+ var bottom = flipY ? 0 : (height - halfHeight);
+
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]);
+
+ // Check the top and bottom halves and make sure they have the right color.
+ debug("Checking " + (flipY ? "top" : "bottom"));
+ wtu.checkCanvasRect(gl, 0, bottom, width, halfHeight, redColor, "shouldBe " + redColor);
+ debug("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, 0, top, width, halfHeight, greenColor, "shouldBe " + greenColor);
+
+ if (false) {
+ var ma = wtu.makeImageFromCanvas(canvas);
+ document.getElementById("console").appendChild(ma);
+
+ var m = wtu.makeImageFromCanvas(gl.canvas);
+ document.getElementById("console").appendChild(m);
+ document.getElementById("console").appendChild(document.createElement("hr"));
+ }
+
+ return texture;
+ }
+
+ function runTest()
+ {
+ var ctx = wtu.create3DContext();
+ var canvas = ctx.canvas;
+
+ var cases = [
+ { flipY: true, init: setCanvasToMin },
+ { flipY: false },
+ { flipY: true, init: setCanvasTo257x257 },
+ { flipY: false },
+ ];
+
+ function runTexImageTest(bindingTarget) {
+ var program;
+ if (bindingTarget == gl.TEXTURE_3D) {
+ program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ } else {
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ }
+
+ return new Promise(function(resolve, reject) {
+ var count = 4;
+ var caseNdx = 0;
+ var texture = undefined;
+ function runNextTest() {
+ var c = cases[caseNdx];
+ if (c.init) {
+ c.init(ctx, bindingTarget);
+ }
+ texture = runOneIteration(canvas, c.flipY, program, bindingTarget, texture);
+ // for the first 2 iterations always make a new texture.
+ if (count > 2) {
+ texture = undefined;
+ }
+ ++caseNdx;
+ if (caseNdx == cases.length) {
+ caseNdx = 0;
+ --count;
+ if (!count) {
+ resolve("SUCCESS");
+ return;
+ }
+ }
+ wtu.waitForComposite(runNextTest);
+ }
+ runNextTest();
+ });
+ }
+
+ runTexImageTest(gl.TEXTURE_3D).then(function(val) {
+ runTexImageTest(gl.TEXTURE_2D_ARRAY).then(function(val) {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ finishTest();
+ });
+ });
+ }
+
+ return init;
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js
new file mode 100644
index 000000000..ba5be49a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js
@@ -0,0 +1,818 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+var TexImageUtils = (function() {
+
+ "use strict";
+
+ var wtu = WebGLTestUtils;
+
+ /**
+ * A vertex shader for a single texture.
+ * @type {string}
+ */
+ var simpleTextureVertexShaderES3 = [
+ '#version 300 es',
+ 'in vec4 vPosition;',
+ 'in vec2 texCoord0;',
+ 'out vec2 texCoord;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ ' texCoord = texCoord0;',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single unsigned integer texture.
+ * @type {string}
+ */
+ // Note we always output 1.0 for alpha because if the texture does not contain
+ // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+ var simpleUintTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump usampler2D tex;',
+ 'in vec2 texCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' uvec4 data = texture(tex, texCoord);',
+ ' fragData = vec4(float(data[0])/255.0,',
+ ' float(data[1])/255.0,',
+ ' float(data[2])/255.0,',
+ ' 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single signed integer texture.
+ * @type {string}
+ */
+ // Note we always output 1.0 for alpha because if the texture does not contain
+ // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+ var simpleIntTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump isampler2D tex;',
+ 'in vec2 texCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' ivec4 data = texture(tex, texCoord);',
+ ' fragData = vec4(float(data[0])/255.0,',
+ ' float(data[1])/255.0,',
+ ' float(data[2])/255.0,',
+ ' 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single cube map unsigned integer texture.
+ * @type {string}
+ */
+ // Note we always output 1.0 for alpha because if the texture does not contain
+ // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+ var simpleCubeMapUintTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump usamplerCube tex;',
+ 'uniform int face;',
+ 'in vec2 texCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ // Transform [0, 1] -> [-1, 1]
+ ' vec2 texC2 = (texCoord * 2.) - 1.;',
+ // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord.
+ ' vec3 texCube = vec3(0., 0., 0.);',
+ ' if (face == 34069) {', // TEXTURE_CUBE_MAP_POSITIVE_X
+ ' texCube = vec3(1., -texC2.y, -texC2.x);',
+ ' } else if (face == 34070) {', // TEXTURE_CUBE_MAP_NEGATIVE_X
+ ' texCube = vec3(-1., -texC2.y, texC2.x);',
+ ' } else if (face == 34071) {', // TEXTURE_CUBE_MAP_POSITIVE_Y
+ ' texCube = vec3(texC2.x, 1., texC2.y);',
+ ' } else if (face == 34072) {', // TEXTURE_CUBE_MAP_NEGATIVE_Y
+ ' texCube = vec3(texC2.x, -1., -texC2.y);',
+ ' } else if (face == 34073) {', // TEXTURE_CUBE_MAP_POSITIVE_Z
+ ' texCube = vec3(texC2.x, -texC2.y, 1.);',
+ ' } else if (face == 34074) {', // TEXTURE_CUBE_MAP_NEGATIVE_Z
+ ' texCube = vec3(-texC2.x, -texC2.y, -1.);',
+ ' }',
+ ' uvec4 data = texture(tex, texCube);',
+ ' fragData = vec4(float(data[0])/255.0,',
+ ' float(data[1])/255.0,',
+ ' float(data[2])/255.0,',
+ ' 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single cube map signed integer texture.
+ * @type {string}
+ */
+ // Note we always output 1.0 for alpha because if the texture does not contain
+ // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+ var simpleCubeMapIntTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump isamplerCube tex;',
+ 'uniform int face;',
+ 'in vec2 texCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ // Transform [0, 1] -> [-1, 1]
+ ' vec2 texC2 = (texCoord * 2.) - 1.;',
+ // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord.
+ ' vec3 texCube = vec3(0., 0., 0.);',
+ ' if (face == 34069) {', // TEXTURE_CUBE_MAP_POSITIVE_X
+ ' texCube = vec3(1., -texC2.y, -texC2.x);',
+ ' } else if (face == 34070) {', // TEXTURE_CUBE_MAP_NEGATIVE_X
+ ' texCube = vec3(-1., -texC2.y, texC2.x);',
+ ' } else if (face == 34071) {', // TEXTURE_CUBE_MAP_POSITIVE_Y
+ ' texCube = vec3(texC2.x, 1., texC2.y);',
+ ' } else if (face == 34072) {', // TEXTURE_CUBE_MAP_NEGATIVE_Y
+ ' texCube = vec3(texC2.x, -1., -texC2.y);',
+ ' } else if (face == 34073) {', // TEXTURE_CUBE_MAP_POSITIVE_Z
+ ' texCube = vec3(texC2.x, -texC2.y, 1.);',
+ ' } else if (face == 34074) {', // TEXTURE_CUBE_MAP_NEGATIVE_Z
+ ' texCube = vec3(-texC2.x, -texC2.y, -1.);',
+ ' }',
+ ' ivec4 data = texture(tex, texCube);',
+ ' fragData = vec4(float(data[0])/255.0,',
+ ' float(data[1])/255.0,',
+ ' float(data[2])/255.0,',
+ ' 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single 3D texture.
+ * @type {string}
+ */
+ // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default.
+ var simple3DTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump sampler3D tex;',
+ 'in vec2 texCoord;',
+ 'uniform float uRCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' fragData = vec4(texture(tex, vec3(texCoord, uRCoord)).rgb, 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single 3D unsigned integer texture.
+ * @type {string}
+ */
+ // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default.
+ // Note we always output 1.0 for alpha because if the texture does not contain
+ // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+ var simple3DUintTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump usampler3D tex;',
+ 'in vec2 texCoord;',
+ 'uniform float uRCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' uvec4 data = texture(tex, vec3(texCoord, uRCoord));',
+ ' fragData = vec4(float(data[0])/255.0,',
+ ' float(data[1])/255.0,',
+ ' float(data[2])/255.0,',
+ ' 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single 3D signed integer texture.
+ * @type {string}
+ */
+ // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default.
+ // Note we always output 1.0 for alpha because if the texture does not contain
+ // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+ var simple3DIntTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump isampler3D tex;',
+ 'in vec2 texCoord;',
+ 'uniform float uRCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' ivec4 data = texture(tex, vec3(texCoord, uRCoord));',
+ ' fragData = vec4(float(data[0])/255.0,',
+ ' float(data[1])/255.0,',
+ ' float(data[2])/255.0,',
+ ' 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single 2D_ARRAY texture.
+ * @type {string}
+ */
+ // Note that the first image in the array (selected by the uniform
+ // uRCoord) is used by default.
+ var simple2DArrayTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump sampler2DArray tex;',
+ 'in vec2 texCoord;',
+ 'uniform float uRCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' fragData = vec4(texture(tex, vec3(texCoord, uRCoord)).rgb, 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single 2D_ARRAY unsigned integer texture.
+ * @type {string}
+ */
+ // Note that the first image in the array (selected by the uniform
+ // uRCoord) is used by default.
+ // Note we always output 1.0 for alpha because if the texture does not contain
+ // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+ var simple2DArrayUintTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump usampler2DArray tex;',
+ 'in vec2 texCoord;',
+ 'uniform float uRCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' uvec4 data = texture(tex, vec3(texCoord, uRCoord));',
+ ' fragData = vec4(float(data[0])/255.0,',
+ ' float(data[1])/255.0,',
+ ' float(data[2])/255.0,',
+ ' 1.0);',
+ '}'].join('\n');
+
+ /**
+ * A fragment shader for a single 2D_ARRAY signed integer texture.
+ * @type {string}
+ */
+ // Note that the first image in the array (selected by the uniform
+ // uRCoord) is used by default.
+ // Note we always output 1.0 for alpha because if the texture does not contain
+ // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+ var simple2DArrayIntTextureFragmentShaderES3 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'uniform mediump isampler2DArray tex;',
+ 'in vec2 texCoord;',
+ 'uniform float uRCoord;',
+ 'out vec4 fragData;',
+ 'void main() {',
+ ' ivec4 data = texture(tex, vec3(texCoord, uRCoord));',
+ ' fragData = vec4(float(data[0])/255.0,',
+ ' float(data[1])/255.0,',
+ ' float(data[2])/255.0,',
+ ' 1.0);',
+ '}'].join('\n');
+
+
+ /**
+ * Creates a simple texture vertex shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimpleTextureVertexShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simpleTextureVertexShaderES3, gl.VERTEX_SHADER);
+ };
+
+ /**
+ * Creates a simple unsigned integer texture fragment shader.
+ * Output is scaled by 1/255 to bring the result into normalized float range.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimpleUintTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simpleUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple signed integer texture fragment shader.
+ * Output is scaled by 1/255 to bring the result into normalized float range.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimpleIntTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simpleIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple cube map unsigned integer texture fragment shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimpleCubeMapUintTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simpleCubeMapUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple cube map signed integer texture fragment shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimpleCubeMapIntTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simpleCubeMapIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple 3D texture fragment shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimple3DTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simple3DTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple 3D unsigned integer texture fragment shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimple3DUintTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simple3DUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple 3D signed integer texture fragment shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimple3DIntTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simple3DIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple 2D_ARRAY texture fragment shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimple2DArrayTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simple2DArrayTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple 2D_ARRAY integer texture fragment shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLShader}
+ */
+ var setupSimple2DArrayUintTextureFragmentShader = function(gl) {
+ return WebGLTestUtils.loadShader(gl, simple2DArrayUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+ };
+
+ /**
+ * Creates a simple unsigned integer texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimpleUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+ {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl),
+ fs = setupSimpleUintTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple signed integer texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimpleIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+ {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl),
+ fs = setupSimpleIntTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple cube map unsigned integer texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimpleCubeMapUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl);
+ var fs = setupSimpleCubeMapUintTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple cube map signed integer texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimpleCubeMapIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl);
+ var fs = setupSimpleCubeMapIntTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple 3D texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimple3DTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+ {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl),
+ fs = setupSimple3DTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple 3D unsigned integer texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimple3DUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+ {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl),
+ fs = setupSimple3DUintTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple 3D signed integer texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimple3DIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+ {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl),
+ fs = setupSimple3DIntTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple 2D_ARRAY texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimple2DArrayTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+ {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl),
+ fs = setupSimple2DArrayTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple 2D_ARRAY unsigned integer texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimple2DArrayUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+ {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl),
+ fs = setupSimple2DArrayUintTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a simple 2D_ARRAY signed integer texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+ var setupSimple2DArrayIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+ {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ var vs = setupSimpleTextureVertexShader(gl),
+ fs = setupSimple2DArrayIntTextureFragmentShader(gl);
+ if (!vs || !fs) {
+ return null;
+ }
+ var program = WebGLTestUtils.setupProgram(
+ gl,
+ [vs, fs],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+ if (!program) {
+ gl.deleteShader(fs);
+ gl.deleteShader(vs);
+ }
+ gl.useProgram(program);
+ return program;
+ };
+
+ /**
+ * Creates a program and buffers for rendering a unsigned integer textured quad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLProgram}
+ */
+ var setupUintTexturedQuad = function(gl) {
+ var program = setupSimpleUintTextureProgram(gl);
+ wtu.setupUnitQuad(gl);
+ return program;
+ };
+
+ /**
+ * Creates a program and buffers for rendering a signed integer textured quad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLProgram}
+ */
+ var setupIntTexturedQuad = function(gl) {
+ var program = setupSimpleIntTextureProgram(gl);
+ wtu.setupUnitQuad(gl);
+ return program;
+ };
+
+ /**
+ * Creates a program and buffers for rendering a textured quad with
+ * a cube map unsigned integer texture.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLProgram}
+ */
+ var setupUintTexturedQuadWithCubeMap = function(gl)
+ {
+ var program = setupSimpleCubeMapUintTextureProgram(gl);
+ wtu.setupUnitQuad(gl);
+ return program;
+ };
+
+ /**
+ * Creates a program and buffers for rendering a textured quad with
+ * a cube map signed integer texture.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {!WebGLProgram}
+ */
+ var setupIntTexturedQuadWithCubeMap = function(gl)
+ {
+ var program = setupSimpleCubeMapIntTextureProgram(gl);
+ wtu.setupUnitQuad(gl);
+ return program;
+ };
+
+ /**
+ * Does the GL internal format represent an unsigned integer format
+ * texture?
+ * @return {boolean}
+ */
+ var isUintFormat = function(internalFormat)
+ {
+ return (internalFormat == "R8UI" || internalFormat == "RG8UI" || internalFormat == "RGB8UI" || internalFormat == "RGBA8UI" ||
+ internalFormat == "R16UI" || internalFormat == "RG16UI" || internalFormat == "RGB16UI" || internalFormat == "RGBA16UI" ||
+ internalFormat == "R32UI" || internalFormat == "RG32UI" || internalFormat == "RGB32UI" || internalFormat == "RGBA32UI");
+ };
+
+ /**
+ * Does the GL internal format represent an signed integer format
+ * texture?
+ * @return {boolean}
+ */
+ var isIntFormat = function(internalFormat)
+ {
+ return (internalFormat == "R8I" || internalFormat == "RG8I" || internalFormat == "RGB8I" || internalFormat == "RGBA8I" ||
+ internalFormat == "R16I" || internalFormat == "RG16I" || internalFormat == "RGB16I" || internalFormat == "RGBA16I" ||
+ internalFormat == "R32I" || internalFormat == "RG32I" || internalFormat == "RGB32I" || internalFormat == "RGBA32I");
+ };
+
+ /**
+ * Createa a program and buffers for rendering a textured quad for
+ * tex-image-and-sub-image tests. Handle selection of correct
+ * program to handle texture format.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} internalFormat The internal format for texture to be tested.
+ */
+ var setupTexturedQuad = function(gl, internalFormat)
+ {
+ if (isUintFormat(internalFormat))
+ return setupUintTexturedQuad(gl);
+ if (isIntFormat(internalFormat))
+ return setupIntTexturedQuad(gl);
+ return wtu.setupTexturedQuad(gl);
+ };
+
+ /**
+ * Createa a program and buffers for rendering a textured quad with
+ * a cube map for tex-image-and-sub-image tests. Handle selection of
+ * correct program to handle texture format.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} internalFormat The internal format for texture to be tested.
+ */
+ function setupTexturedQuadWithCubeMap(gl, internalFormat)
+ {
+ if (isUintFormat(internalFormat))
+ return setupUintTexturedQuadWithCubeMap(gl);
+ if (isIntFormat(internalFormat))
+ return setupIntTexturedQuadWithCubeMap(gl);
+ return wtu.setupTexturedQuadWithCubeMap(gl);
+ }
+
+ /**
+ * Createa a program and buffers for rendering a textured quad with a 3D texture
+ * for tex-image-and-sub-image tests. Handle selection of correct
+ * program to handle texture format.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} internalFormat The internal format for texture to be tested.
+ */
+ var setupTexturedQuadWith3D = function(gl, internalFormat)
+ {
+ var program;
+ if (isUintFormat(internalFormat))
+ program = setupSimple3DUintTextureProgram(gl);
+ else if (isIntFormat(internalFormat))
+ program = setupSimple3DIntTextureProgram(gl);
+ else
+ program = setupSimple3DTextureProgram(gl);
+ var uRCoordLoc = gl.getUniformLocation(program, 'uRCoord');
+ gl.uniform1f(uRCoordLoc, 0.0);
+ wtu.setupUnitQuad(gl);
+ return program;
+ };
+
+ /**
+ * Createa a program and buffers for rendering a textured quad with a 2D_ARRAY
+ * texture for tex-image-and-sub-image tests. Handle selection of correct
+ * program to handle texture format.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} internalFormat The internal format for texture to be tested.
+ */
+ var setupTexturedQuadWith2DArray = function(gl, internalFormat)
+ {
+ var program;
+ if (isUintFormat(internalFormat))
+ program = setupSimple2DArrayUintTextureProgram(gl);
+ else if (isIntFormat(internalFormat))
+ program = setupSimple2DArrayIntTextureProgram(gl);
+ else
+ program = setupSimple2DArrayTextureProgram(gl);
+ var uRCoordLoc = gl.getUniformLocation(program, 'uRCoord');
+ gl.uniform1f(uRCoordLoc, 0.0);
+ wtu.setupUnitQuad(gl);
+ return program;
+ };
+
+ return {
+ setupTexturedQuad: setupTexturedQuad,
+ setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
+ setupTexturedQuadWith3D: setupTexturedQuadWith3D,
+ setupTexturedQuadWith2DArray: setupTexturedQuadWith2DArray
+ };
+
+}());
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js
new file mode 100644
index 000000000..af7f3d141
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js
@@ -0,0 +1,408 @@
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+
+function runOneIterationImageBitmapTest(useTexSubImage, bindingTarget, program, bitmap, flipY, premultiplyAlpha, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu)
+{
+ var halfRed = [128, 0, 0];
+ var halfGreen = [0, 128, 0];
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+ var blackColor = [0, 0, 0];
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ halfGreen = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ switch (gl[internalFormat]) {
+ case gl.SRGB8:
+ case gl.SRGB8_ALPHA8:
+ // Math.pow((128 / 255 + 0.055) / 1.055, 2.4) * 255 = 55
+ halfRed = [55, 0, 0];
+ halfGreen = [0, 55, 0];
+ break;
+ default:
+ break;
+ }
+
+ var str;
+ if (optionsVal.is3D) {
+ str = 'Testing ' + (useTexSubImage ? 'texSubImage3D' : 'texImage3D') +
+ ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha +
+ ', bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY');
+ } else {
+ str = 'Testing ' + (useTexSubImage ? 'texSubImage2D' : 'texImage2D') +
+ ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha +
+ ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP');
+ }
+ debug(str);
+ bufferedLogToConsole(str);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Enable writes to the RGBA channels
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+
+ var targets = [bindingTarget];
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+ }
+
+ bufferedLogToConsole("Starts uploading the image into texture");
+ // Upload the image into the texture
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (optionsVal.is3D) {
+ gl.texImage3D(targets[tt], 0, gl[internalFormat], bitmap.width, bitmap.height, 1 /* depth */, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage3D(targets[tt], 0, 0, 0, 0, bitmap.width, bitmap.height, 1,
+ gl[pixelFormat], gl[pixelType], bitmap);
+ } else {
+ if (useTexSubImage) {
+ // Initialize the texture to black first
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], bitmap.width, bitmap.height, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], bitmap);
+ } else {
+ gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], bitmap);
+ }
+ }
+ }
+ bufferedLogToConsole("Uploading texture completed");
+
+ var width = gl.canvas.width;
+ var halfWidth = Math.floor(width / 2);
+ var quaterWidth = Math.floor(halfWidth / 2);
+ var height = gl.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ var quaterHeight = Math.floor(halfHeight / 2);
+
+ var top = flipY ? quaterHeight : (height - halfHeight + quaterHeight);
+ var bottom = flipY ? (height - halfHeight + quaterHeight) : quaterHeight;
+
+ var tl = redColor;
+ var tr = premultiplyAlpha ? ((optionsVal.alpha == 0.5) ? halfRed : (optionsVal.alpha == 1) ? redColor : blackColor) : redColor;
+ var bl = greenColor;
+ var br = premultiplyAlpha ? ((optionsVal.alpha == 0.5) ? halfGreen : (optionsVal.alpha == 1) ? greenColor : blackColor) : greenColor;
+
+ var loc;
+ var skipCorner = false;
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ loc = gl.getUniformLocation(program, "face");
+ switch (pixelFormat) {
+ case gl.RED_INTEGER:
+ case gl.RG_INTEGER:
+ case gl.RGB_INTEGER:
+ case gl.RGBA_INTEGER:
+ // https://github.com/KhronosGroup/WebGL/issues/1819
+ skipCorner = true;
+ break;
+ }
+ }
+
+ var tolerance = 10;
+ for (var tt = 0; tt < targets.length; ++tt) {
+ if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+ gl.uniform1i(loc, targets[tt]);
+ }
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+
+ // Check the top pixel and bottom pixel and make sure they have
+ // the right color.
+ bufferedLogToConsole("Checking " + (flipY ? "top" : "bottom"));
+ wtu.checkCanvasRect(gl, quaterWidth, bottom, 2, 2, tl, "shouldBe " + tl);
+ if (!skipCorner && !flipY) {
+ wtu.checkCanvasRect(gl, halfWidth + quaterWidth, bottom, 2, 2, tr, "shouldBe " + tr, tolerance);
+ }
+ bufferedLogToConsole("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, quaterWidth, top, 2, 2, bl, "shouldBe " + bl);
+ if (!skipCorner && flipY) {
+ wtu.checkCanvasRect(gl, halfWidth + quaterWidth, top, 2, 2, br, "shouldBe " + br, tolerance);
+ }
+ }
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+}
+
+function resetUnpackParams(gl)
+{
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, 0);
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, 0);
+ gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0);
+}
+
+function runOneIterationImageBitmapTestSubSource(useTexSubImage, bindingTarget, program, bitmap, flipY, premultiplyAlpha, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu)
+{
+ var halfRed = [128, 0, 0];
+ var halfGreen = [0, 128, 0];
+ var redColor = [255, 0, 0];
+ var greenColor = [0, 255, 0];
+ var blackColor = [0, 0, 0];
+
+ switch (gl[pixelFormat]) {
+ case gl.RED:
+ case gl.RED_INTEGER:
+ greenColor = [0, 0, 0];
+ halfGreen = [0, 0, 0];
+ break;
+ default:
+ break;
+ }
+
+ switch (gl[internalFormat]) {
+ case gl.SRGB8:
+ case gl.SRGB8_ALPHA8:
+ // Math.pow((128 / 255 + 0.055) / 1.055, 2.4) * 255 = 55
+ halfRed = [55, 0, 0];
+ halfGreen = [0, 55, 0];
+ break;
+ default:
+ break;
+ }
+
+ var str;
+ if (optionsVal.is3D) {
+ str = 'Testing ' + (useTexSubImage ? 'texSubImage3D' : 'texImage3D') + '[SubSource]' +
+ ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha +
+ ', bindingTarget=TEXTURE_3D';
+ } else {
+ str = 'Testing ' + (useTexSubImage ? 'texSubImage2D' : 'texImage2D') + '[SubSource]' +
+ ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha +
+ ', bindingTarget=TEXTURE_2D';
+ }
+ debug(str);
+ bufferedLogToConsole(str);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ // Enable writes to the RGBA channels
+ gl.colorMask(1, 1, 1, 0);
+ var texture = gl.createTexture();
+ // Bind the texture to texture unit 0
+ gl.bindTexture(bindingTarget, texture);
+ // Set up texture parameters
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+
+ var srcTL = redColor;
+ var srcTR = premultiplyAlpha ? ((optionsVal.alpha == 0.5) ? halfRed : (optionsVal.alpha == 1) ? redColor : blackColor) : redColor;
+ var srcBL = greenColor;
+ var srcBR = premultiplyAlpha ? ((optionsVal.alpha == 0.5) ? halfGreen : (optionsVal.alpha == 1) ? greenColor : blackColor) : greenColor;
+
+ var tl, tr, bl, br;
+
+ bufferedLogToConsole("Starts uploading the image into texture");
+ // Upload the image into the texture
+ if (optionsVal.is3D) {
+ if (useTexSubImage) {
+ // Initialize the texture to black first
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], bitmap.width, bitmap.height, 1 /* depth */, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ // Only upload the left half image to the right half texture.
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, 0);
+ gl.texSubImage3D(bindingTarget, 0, bitmap.width / 2, 0, 0, bitmap.width / 2, bitmap.height, 1,
+ gl[pixelFormat], gl[pixelType], bitmap);
+ tl = blackColor;
+ tr = srcTL;
+ bl = blackColor;
+ br = srcBL;
+ } else {
+ // Only upload the bottom middle quarter image
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, bitmap.height / 2);
+ gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, 0);
+ gl.texImage3D(bindingTarget, 0, gl[internalFormat], bitmap.width, bitmap.height / 2, 1 /* depth */, 0,
+ gl[pixelFormat], gl[pixelType], bitmap);
+ if (!flipY) {
+ tl = srcBL;
+ tr = srcBR;
+ bl = srcBL;
+ br = srcBR;
+ } else {
+ tl = srcTL;
+ tr = srcTR;
+ bl = srcTL;
+ br = srcTR;
+ }
+ }
+ } else {
+ if (useTexSubImage) {
+ // Initialize the texture to black first
+ gl.texImage2D(bindingTarget, 0, gl[internalFormat], bitmap.width, bitmap.height, 0,
+ gl[pixelFormat], gl[pixelType], null);
+ // Only upload the left half image to the right half texture.
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
+ gl.texSubImage2D(bindingTarget, 0, bitmap.width / 2, 0, bitmap.width / 2, bitmap.height,
+ gl[pixelFormat], gl[pixelType], bitmap);
+ tl = blackColor;
+ tr = srcTL;
+ bl = blackColor;
+ br = srcBL;
+ } else {
+ // Only upload the right bottom image.
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, bitmap.width / 2);
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, bitmap.height / 2);
+ gl.texImage2D(bindingTarget, 0, gl[internalFormat], bitmap.width / 2, bitmap.height / 2, 0,
+ gl[pixelFormat], gl[pixelType], bitmap);
+ resetUnpackParams(gl);
+ if (!flipY) {
+ tl = srcBR;
+ tr = srcBR;
+ bl = srcBR;
+ br = srcBR;
+ } else {
+ tl = srcTR;
+ tr = srcTR;
+ bl = srcTR;
+ br = srcTR;
+ }
+ }
+ }
+ bufferedLogToConsole("Uploading texture completed");
+
+ var width = gl.canvas.width;
+ var halfWidth = Math.floor(width / 2);
+ var quaterWidth = Math.floor(halfWidth / 2);
+ var height = gl.canvas.height;
+ var halfHeight = Math.floor(height / 2);
+ var quaterHeight = Math.floor(halfHeight / 2);
+
+ var top = flipY ? quaterHeight : (height - halfHeight + quaterHeight);
+ var bottom = flipY ? (height - halfHeight + quaterHeight) : quaterHeight;
+
+
+ var tolerance = 10;
+ // Draw the triangles
+ wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
+
+ // Check the top pixel and bottom pixel and make sure they have
+ // the right color.
+ // For right side, check pixels closer to left to avoid border in the video tests.
+ bufferedLogToConsole("Checking " + (flipY ? "top" : "bottom"));
+ wtu.checkCanvasRect(gl, quaterWidth, bottom, 2, 2, tl, "shouldBe " + tl, tolerance);
+ wtu.checkCanvasRect(gl, halfWidth + quaterWidth / 2, bottom, 2, 2, tr, "shouldBe " + tr, tolerance);
+ bufferedLogToConsole("Checking " + (flipY ? "bottom" : "top"));
+ wtu.checkCanvasRect(gl, quaterWidth, top, 2, 2, bl, "shouldBe " + bl, tolerance);
+ wtu.checkCanvasRect(gl, halfWidth + quaterWidth / 2, top, 2, 2, br, "shouldBe " + br, tolerance);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+}
+
+function runTestOnBindingTargetImageBitmap(bindingTarget, program, bitmaps, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu)
+{
+ var cases = [
+ { sub: false, bitmap: bitmaps.noFlipYPremul, flipY: false, premultiply: true },
+ { sub: true, bitmap: bitmaps.noFlipYPremul, flipY: false, premultiply: true },
+ { sub: false, bitmap: bitmaps.noFlipYUnpremul, flipY: false, premultiply: false },
+ { sub: true, bitmap: bitmaps.noFlipYUnpremul, flipY: false, premultiply: false },
+ { sub: false, bitmap: bitmaps.flipYPremul, flipY: true, premultiply: true },
+ { sub: true, bitmap: bitmaps.flipYPremul, flipY: true, premultiply: true },
+ { sub: false, bitmap: bitmaps.flipYUnpremul, flipY: true, premultiply: false },
+ { sub: true, bitmap: bitmaps.flipYUnpremul, flipY: true, premultiply: false },
+ ];
+
+ for (var i in cases) {
+ runOneIterationImageBitmapTest(cases[i].sub, bindingTarget, program, cases[i].bitmap,
+ cases[i].flipY, cases[i].premultiply, optionsVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu);
+ }
+
+ if (wtu.getDefault3DContextVersion() > 1 &&
+ (bindingTarget == gl.TEXTURE_2D || bindingTarget == gl.TEXTURE_3D)) {
+ // SKip testing source sub region on TEXTURE_CUBE_MAP and TEXTURE_2D_ARRAY to save running time.
+ for (var i in cases) {
+ runOneIterationImageBitmapTestSubSource(cases[i].sub, bindingTarget, program, cases[i].bitmap,
+ cases[i].flipY, cases[i].premultiply, optionsVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu);
+ }
+ }
+}
+
+function runImageBitmapTestInternal(bitmaps, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D)
+{
+ var optionsVal = {alpha: alphaVal, is3D: is3D};
+ var program;
+ if (is3D) {
+ program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
+ runTestOnBindingTargetImageBitmap(gl.TEXTURE_3D, program, bitmaps, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu);
+ } else {
+ program = tiu.setupTexturedQuad(gl, internalFormat);
+ runTestOnBindingTargetImageBitmap(gl.TEXTURE_2D, program, bitmaps, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu);
+ }
+
+ // cube map texture must be square
+ if (bitmaps.noFlipYPremul.width == bitmaps.noFlipYPremul.height) {
+ if (is3D) {
+ program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
+ runTestOnBindingTargetImageBitmap(gl.TEXTURE_2D_ARRAY, program, bitmaps, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu);
+ } else {
+ program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+ runTestOnBindingTargetImageBitmap(gl.TEXTURE_CUBE_MAP, program, bitmaps, optionsVal,
+ internalFormat, pixelFormat, pixelType, gl, tiu, wtu);
+ }
+ }
+}
+
+function runImageBitmapTest(source, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D)
+{
+ var bitmaps = [];
+ var p1 = createImageBitmap(source, {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.noFlipYPremul = imageBitmap });
+ var p2 = createImageBitmap(source, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.noFlipYUnpremul = imageBitmap });
+ var p3 = createImageBitmap(source, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.flipYPremul = imageBitmap });
+ var p4 = createImageBitmap(source, {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.flipYUnpremul = imageBitmap });
+ Promise.all([p1, p2, p3, p4]).then(function() {
+ bufferedLogToConsole("All createImageBitmap promises are resolved");
+ runImageBitmapTestInternal(bitmaps, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D);
+ }, function() {
+ // createImageBitmap with options could be rejected if it is not supported
+ finishTest();
+ return;
+ });
+}
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js
new file mode 100644
index 000000000..154dfbddf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js
@@ -0,0 +1,580 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This test relies on the surrounding web page defining a variable
+// "contextVersion" which indicates what version of WebGL it's running
+// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc.
+
+"use strict";
+description("Validate tex functions input parameters");
+
+var wtu = WebGLTestUtils;
+var gl = null;
+var tex = null;
+var error = 0;
+
+shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, contextVersion)");
+shouldBeNonNull("tex = gl.createTexture()");
+gl.bindTexture(gl.TEXTURE_2D, tex);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+function enumToString(value) {
+ return wtu.glEnumToString(gl, value);
+}
+
+function testTexParameter(testCase) {
+ var msg = "paramName: " + enumToString(testCase.pname);
+ error = testCase.expectedError;
+ gl.texParameteri(testCase.target, testCase.pname, testCase.param);
+ wtu.glErrorShouldBe(gl, error, msg);
+ gl.texParameterf(testCase.target, testCase.pname, testCase.param);
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+function testGetTexParameter(testCase) {
+ var msg = "paramName: " + enumToString(testCase.pname);
+ error = testCase.expectedError;
+ gl.getTexParameter(testCase.target, testCase.pname);
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+function testTexImage2D(testCase) {
+ var level = 0;
+ var width = 16;
+ var height = 16;
+ var msg = " internalFormat: " + enumToString(testCase.internalFormat) +
+ " target: " + enumToString(testCase.target) +
+ " format: " + enumToString(testCase.format) +
+ " type: " + enumToString(testCase.type) +
+ " border: " + testCase.border;
+
+ gl.texImage2D(testCase.target, level, testCase.internalFormat, width, height, testCase.border, testCase.format, testCase.type, null);
+ error = testCase.expectedError;
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+function testTexSubImage2D(testCase) {
+ var level = 0;
+ var xoffset = 0;
+ var yoffset = 0;
+ var width = 16;
+ var height = 16;
+ var msg = " format: " + enumToString(testCase.format) +
+ " type: " + enumToString(testCase.type);
+ var array = new Uint8Array(width * height * 4);
+
+ gl.texSubImage2D(testCase.target, level, xoffset, yoffset, width, height, testCase.format, testCase.type, array);
+ error = testCase.expectedError;
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+function testCopyTexImage2D(testCase) {
+ var level = 0;
+ var x = 0;
+ var y = 0;
+ var width = 16;
+ var height = 16;
+ var msg = " colorBufferFormat: " + enumToString(testCase.colorBufferFormat) +
+ " internalFormat: " + enumToString(testCase.internalFormat) +
+ " target: " + enumToString(testCase.target) +
+ " border: " + testCase.border;
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, testCase.colorBufferFormat, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ gl.copyTexImage2D(testCase.target, level, testCase.internalFormat, x, y, width, height, testCase.border);
+ error = testCase.expectedError;
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+function testCopyTexSubImage2D(testCase) {
+ var level = 0;
+ var x = 0;
+ var y = 0;
+ var width = 16;
+ var height = 16;
+ var xoffset = 0;
+ var yoffset = 0;
+ var border = 0;
+ var type = gl.UNSIGNED_BYTE;
+ var msg = " colorBufferFormat: " + enumToString(testCase.colorBufferFormat) +
+ " internalFormat: " + enumToString(testCase.internalFormat) +
+ " target: " + enumToString(testCase.target);
+
+ gl.renderbufferStorage(gl.RENDERBUFFER, testCase.colorBufferFormat, width, height);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+ gl.texImage2D(testCase.target, level, testCase.internalFormat, xoffset + width, yoffset + height, border, testCase.internalFormat, type, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+ gl.copyTexSubImage2D(testCase.target, level, xoffset, yoffset, x, y, width, height);
+ error = testCase.expectedError;
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+function testCopyFromInternalFBO(testCase) {
+ var target = gl.TEXTURE_2D;
+ var level = 0;
+ var x = 0;
+ var y = 0;
+ var width = 16;
+ var height = 16;
+ var xoffset = 0;
+ var yoffset = 0;
+ var border = 0;
+ var type = gl.UNSIGNED_BYTE;
+ var msg = " colorBufferFormat: " + enumToString(testCase.contextAlpha ? gl.RGBA : gl.RGB) +
+ " internalFormat: " + enumToString(testCase.internalFormat);
+
+ if (testCase.contextAlpha) {
+ gl = wtu.create3DContext(null, { alpha: true }, contextVersion);
+ } else {
+ gl = wtu.create3DContext(null, { alpha: false }, contextVersion);
+ }
+ shouldBeNonNull("gl");
+ shouldBeNonNull("tex = gl.createTexture()");
+ gl.bindTexture(target, tex);
+ if (testCase.subImage) {
+ gl.texImage2D(target, level, testCase.internalFormat, xoffset + width, yoffset + height, border, testCase.internalFormat, type, null);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ gl.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+ } else {
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ gl.copyTexImage2D(target, level, testCase.internalFormat, x, y, width, height, border);
+ }
+ error = testCase.expectedError;
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+// Only for WebGL2.0.
+function testTexImage3D(testCase) {
+ var level = 0;
+ var width = 16;
+ var height = 16;
+ var depth = 16;
+ var msg = " internalFormat: " + enumToString(testCase.internalFormat) +
+ " target: " + enumToString(testCase.target) +
+ " format: " + enumToString(testCase.format) +
+ " type: " + enumToString(testCase.type) +
+ " border: " + testCase.border;
+
+ gl.texImage3D(testCase.target, level, testCase.internalFormat, width, height, depth, testCase.border, testCase.format, testCase.type, null);
+ error = testCase.expectedError;
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+function testTexSubImage3D(testCase) {
+ var level = 0;
+ var xoffset = 0;
+ var yoffset = 0;
+ var zoffset = 0;
+ var width = 16;
+ var height = 16;
+ var depth = 16;
+ var msg = " format: " + enumToString(testCase.format) +
+ " type: " + enumToString(testCase.type);
+ var array = new Uint8Array(width * height * depth * 4);
+
+ gl.texSubImage3D(testCase.target, level, xoffset, yoffset, zoffset, width, height, depth, testCase.format, testCase.type, array);
+ error = testCase.expectedError;
+ wtu.glErrorShouldBe(gl, error, msg);
+}
+
+
+// Start checking.
+
+debug("");
+debug("Checking TexParameter: a set of inputs that are valid in GL but invalid in WebGL");
+
+testCases = [
+ { target: 0x0DE0, // GL_TEXTURE_1D
+ pname: gl.TEXTURE_WRAP_T,
+ param: gl.REPEAT,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_2D,
+ pname: gl.TEXTURE_WRAP_T,
+ param: 0x2900, // GL_CLAMP
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_2D,
+ pname: gl.TEXTURE_WRAP_T,
+ param: gl.REPEAT,
+ expectedError: gl.NO_ERROR }
+];
+
+if (contextVersion < 2) {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_2D,
+ pname: 0x813A, // GL_TEXTURE_MIN_LOD
+ param: 0,
+ expectedError: gl.INVALID_ENUM }
+ ]);
+} else {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_2D,
+ pname: 0x8E42, // GL_TEXTURE_SWIZZLE_R
+ param: 0x1903, // GL_RED
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_2D,
+ pname: 0x8072, // GL_TEXTURE_WRAP_R
+ param: 0x2900, // GL_CLAMP
+ expectedError: gl.INVALID_ENUM }
+ ]);
+}
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testTexParameter(testCases[ii]);
+}
+
+debug("");
+debug("Checking GetTexParameter: a set of inputs that are valid in GL but invalid in WebGL");
+
+testCases = [
+ { target: 0x0DE0, // GL_TEXTURE_1D
+ pname: gl.TEXTURE_WRAP_T,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_2D,
+ pname: gl.TEXTURE_WRAP_T,
+ expectedError: gl.NO_ERROR }
+];
+
+if (contextVersion < 2) {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_2D,
+ pname: 0x813A, // GL_TEXTURE_MIN_LOD
+ expectedError: gl.INVALID_ENUM }
+ ]);
+} else {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_2D,
+ pname: 0x8E42, // GL_TEXTURE_SWIZZLE_R
+ expectedError: gl.INVALID_ENUM }
+ ]);
+}
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testGetTexParameter(testCases[ii]);
+}
+
+debug("");
+debug("Checking TexImage2D: a set of inputs that are valid in GL but invalid in WebGL");
+
+var testCases = [
+ { target: 0x8064, // GL_PROXY_TEXTURE_2D
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_2D,
+ internalFormat: 0x1903, // GL_RED
+ border: 0,
+ format: 0x1903, // GL_RED
+ type: gl.UNSIGNED_BYTE,
+ expectedError: [gl.INVALID_ENUM, gl.INVALID_VALUE] },
+ { target: gl.TEXTURE_2D,
+ internalFormat: gl.RGBA,
+ border: 1,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_VALUE },
+ { target: gl.TEXTURE_2D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGB,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_OPERATION },
+ { target: gl.TEXTURE_2D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.NO_ERROR }
+];
+
+if (contextVersion < 2) {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_2D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.BYTE,
+ expectedError: gl.INVALID_ENUM }
+ ]);
+} else {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_2D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.BYTE,
+ expectedError: gl.INVALID_OPERATION },
+ { target: gl.TEXTURE_3D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_ENUM }
+ ]);
+}
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testTexImage2D(testCases[ii]);
+}
+
+debug("");
+debug("Checking TexSubImage2D: a set of inputs that are valid in GL but invalid in WebGL");
+
+testCases = [
+ { target: gl.TEXTURE_2D,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.NO_ERROR }
+];
+
+if (contextVersion < 2) {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_2D,
+ format: 0x1903, // GL_RED
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_2D,
+ format: gl.RGBA,
+ type: gl.BYTE,
+ expectedError: gl.INVALID_ENUM }
+ ]);
+} else {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_2D,
+ format: gl.RED,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_OPERATION },
+ { target: gl.TEXTURE_2D,
+ format: gl.RGBA,
+ type: gl.BYTE,
+ expectedError: gl.INVALID_OPERATION },
+ { target: gl.TEXTURE_3D,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_ENUM },
+ ]);
+}
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testTexSubImage2D(testCases[ii]);
+}
+
+debug("");
+debug("Checking CopyTexImage2D: a set of inputs that are valid in GL but invalid in WebGL");
+
+var colorBuffer = null;
+var fbo = null;
+
+shouldBeNonNull("fbo = gl.createFramebuffer()");
+gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
+gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
+gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+testCases = [
+ { target: gl.TEXTURE_2D,
+ colorBufferFormat: gl.RGB565,
+ internalFormat: 0x8054, // GL_RGB16
+ border: 0,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_2D,
+ colorBufferFormat: gl.RGB565,
+ internalFormat: gl.RGBA,
+ border: 1,
+ expectedError: gl.INVALID_VALUE },
+ { target: gl.TEXTURE_2D,
+ colorBufferFormat: gl.RGB565,
+ internalFormat: gl.RGBA,
+ border: 0,
+ expectedError: gl.INVALID_OPERATION },
+ { target: gl.TEXTURE_2D,
+ colorBufferFormat: gl.RGB565,
+ internalFormat: gl.RGB,
+ border: 0,
+ expectedError: gl.NO_ERROR }
+];
+
+if (contextVersion > 1) {
+ testCases = testCases.concat([
+ { target: gl.TEXTURE_3D,
+ colorBufferFormat: gl.RGB5_A1,
+ internalFormat: gl.RGBA,
+ border: 0,
+ expectedError: gl.INVALID_ENUM }
+ ]);
+}
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testCopyTexImage2D(testCases[ii]);
+}
+
+debug("");
+debug("Checking CopyTexSubImage2D: a set of inputs that are valid in GL but invalid in WebGL");
+
+testCases = [
+ { target: gl.TEXTURE_2D,
+ colorBufferFormat: gl.RGB5_A1,
+ internalFormat: gl.RGBA,
+ expectedError: gl.NO_ERROR },
+ { target: gl.TEXTURE_2D,
+ colorBufferFormat: gl.RGB565,
+ internalFormat: gl.RGBA,
+ expectedError: gl.INVALID_OPERATION }
+];
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testCopyTexSubImage2D(testCases[ii]);
+}
+
+debug("");
+debug("Checking CopyTex{Sub}Image2D: copy from WebGL internal framebuffer");
+
+testCases = [
+ { contextAlpha: true,
+ internalFormat: gl.RGBA,
+ subImage: false,
+ expectedError: gl.NO_ERROR },
+ { contextAlpha: false,
+ internalFormat: gl.RGBA,
+ subImage: false,
+ expectedError: gl.INVALID_OPERATION },
+ { contextAlpha: true,
+ internalFormat: gl.RGBA,
+ subImage: true,
+ expectedError: gl.NO_ERROR },
+ { contextAlpha: false,
+ internalFormat: gl.RGBA,
+ subImage: true,
+ expectedError: gl.INVALID_OPERATION }
+];
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testCopyFromInternalFBO(testCases[ii]);
+}
+
+if (contextVersion > 1) {
+// Create new texture for testing api of WebGL 2.0.
+shouldBeNonNull("tex = gl.createTexture()");
+gl.bindTexture(gl.TEXTURE_3D, tex);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+
+debug("");
+debug("Checking TexImage3D: a set of inputs that are valid in GL but invalid in WebGL");
+
+var testCases = [
+ { target: 0x8070, // GL_PROXY_TEXTURE_3D
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_3D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGB,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_OPERATION },
+ { target: gl.TEXTURE_3D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.BYTE,
+ expectedError: gl.INVALID_OPERATION},
+ { target: gl.TEXTURE_3D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.NO_ERROR }
+];
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testTexImage3D(testCases[ii]);
+}
+
+debug("");
+debug("Checking TexImage3D: bad target, internalformats, formats, types");
+
+var testCases = [
+ { target: gl.TEXTURE_2D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_3D,
+ internalFormat: gl.RG,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_VALUE},
+ { target: gl.TEXTURE_3D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RG8,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_3D,
+ internalFormat: gl.RGBA,
+ border: 0,
+ format: gl.RGBA,
+ type: gl.INT,
+ expectedError: gl.INVALID_OPERATION},
+];
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testTexImage3D(testCases[ii]);
+}
+
+debug("");
+debug("Checking TexSubImage3D: a set of inputs that are valid in GL but invalid in WebGL");
+
+testCases = [
+ { target: gl.TEXTURE_3D,
+ format: 0x80E0, // GL_BGR
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_3D,
+ format: gl.RGBA,
+ type: 0x8032, // GL_UNSIGNED_BYTE_3_3_2
+ expectedError: gl.INVALID_ENUM },
+ { target: gl.TEXTURE_3D,
+ format: gl.RGBA,
+ type: gl.UNSIGNED_BYTE,
+ expectedError: gl.NO_ERROR }
+];
+
+for (var ii = 0; ii < testCases.length; ++ii) {
+ testTexSubImage3D(testCases[ii]);
+}
+
+}
+
+var successfullyParsed = true;
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js
new file mode 100644
index 000000000..462eaae1b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js
@@ -0,0 +1,90 @@
+/*
+** Copyright (c) 2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// The "name" attribute is a concession to browsers which don't
+// implement the "name" property on function objects.
+var testCases =
+ [ {name: "Float32Array",
+ unsigned: false,
+ integral: false,
+ elementSizeInBytes: 4,
+ testValues: [ -500.5, 500.5 ],
+ expectedValues: [ -500.5, 500.5 ]
+ },
+ {name: "Float64Array",
+ unsigned: false,
+ integral: false,
+ elementSizeInBytes: 8,
+ testValues: [ -500.5, 500.5 ],
+ expectedValues: [ -500.5, 500.5 ]
+ },
+ {name: "Int8Array",
+ unsigned: false,
+ integral: true,
+ elementSizeInBytes: 1,
+ testValues: [ -128, 127, -129, 128 ],
+ expectedValues: [ -128, 127, 127, -128 ]
+ },
+ {name: "Int16Array",
+ unsigned: false,
+ integral: true,
+ elementSizeInBytes: 2,
+ testValues: [ -32768, 32767, -32769, 32768 ],
+ expectedValues: [ -32768, 32767, 32767, -32768 ]
+ },
+ {name: "Int32Array",
+ unsigned: false,
+ integral: true,
+ elementSizeInBytes: 4,
+ testValues: [ -2147483648, 2147483647, -2147483649, 2147483648 ],
+ expectedValues: [ -2147483648, 2147483647, 2147483647, -2147483648 ]
+ },
+ {name: "Uint8Array",
+ unsigned: true,
+ integral: true,
+ elementSizeInBytes: 1,
+ testValues: [ 0, 255, -1, 256 ],
+ expectedValues: [ 0, 255, 255, 0 ]
+ },
+ {name: "Uint8ClampedArray",
+ unsigned: true,
+ integral: true,
+ elementSizeInBytes: 1,
+ testValues: [ 0, 255, -1, 256 ],
+ expectedValues: [ 0, 255, 0, 255 ]
+ },
+ {name: "Uint16Array",
+ unsigned: true,
+ integral: true,
+ elementSizeInBytes: 2,
+ testValues: [ 0, 65535, -1, 65536 ],
+ expectedValues: [ 0, 65535, 65535, 0 ]
+ },
+ {name: "Uint32Array",
+ unsigned: true,
+ integral: true,
+ elementSizeInBytes: 4,
+ testValues: [ 0, 4294967295, -1, 4294967296 ],
+ expectedValues: [ 0, 4294967295, 4294967295, 0 ]
+ }
+ ];
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js
new file mode 100644
index 000000000..c68ee07c2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js
@@ -0,0 +1,89 @@
+/*
+** Copyright (c) 2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+function constructTypedArray(type, data) {
+ if (type == 'Int8Array') {
+ return new Int8Array(data);
+ } else if (type == 'Uint8Array') {
+ return new Uint8Array(data);
+ } else if (type == 'Uint8ClampedArray') {
+ return new Uint8ClampedArray(data);
+ } else if (type == 'Int16Array') {
+ return new Int16Array(data);
+ } else if (type == 'Uint16Array') {
+ return new Uint16Array(data);
+ } else if (type == 'Int32Array') {
+ return new Int32Array(data);
+ } else if (type == 'Uint32Array') {
+ return new Uint32Array(data);
+ } else if (type == 'Float32Array') {
+ return new Float32Array(data);
+ } else if (type == 'Float64Array') {
+ return new Float64Array(data);
+ }
+}
+
+function constructDataView(subType, elementSizeInBytes, data) {
+ var setter = "set" + subType;
+ var byteOffset = 0;
+ var buffer = new ArrayBuffer(elementSizeInBytes * data.length);
+ var dataView = new DataView(buffer);
+ for (var ii = 0; ii < data.length; ++ii) {
+ dataView[setter](byteOffset, data[ii]);
+ byteOffset += elementSizeInBytes;
+ }
+ return dataView;
+}
+
+onmessage = function(event) {
+ var message = event.data;
+ if (message.command == 'copy' ||
+ message.command == 'transfer' ||
+ message.command == 'copyBuffer' ||
+ message.command == 'transferBuffer') {
+ var view;
+ if (message.type != 'DataView') {
+ view = constructTypedArray(message.type, message.data);
+ } else {
+ view = constructDataView(message.subType, message.elementSizeInBytes, message.data);
+ }
+ var valueToSend;
+ if (message.command == 'copy' ||
+ message.command == 'transfer') {
+ valueToSend = view;
+ } else {
+ valueToSend = view.buffer;
+ }
+ var transferablesToSend = undefined;
+ if (message.command == 'transfer' ||
+ message.command == 'transferBuffer') {
+ transferablesToSend = [ view.buffer ];
+ }
+ postMessage(valueToSend, transferablesToSend);
+ } else if (message.command == 'pong') {
+ postMessage(message.data, message.transferables);
+ } else if (message.command == 'ignore') {
+ } else {
+ postMessage('error: unknown message');
+ }
+};
diff --git a/dom/canvas/test/webgl-conf/checkout/js/webgl-test-harness.js b/dom/canvas/test/webgl-conf/checkout/js/webgl-test-harness.js
new file mode 100644
index 000000000..0287bf6ec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/webgl-test-harness.js
@@ -0,0 +1,659 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+// This is a test harness for running javascript tests in the browser.
+// The only identifier exposed by this harness is WebGLTestHarnessModule.
+//
+// To use it make an HTML page with an iframe. Then call the harness like this
+//
+// function reportResults(type, msg, success) {
+// ...
+// return true;
+// }
+//
+// var fileListURL = '00_test_list.txt';
+// var testHarness = new WebGLTestHarnessModule.TestHarness(
+// iframe,
+// fileListURL,
+// reportResults,
+// options);
+//
+// The harness will load the fileListURL and parse it for the URLs, one URL
+// per line preceded by options, see below. URLs should be on the same domain
+// and at the same folder level or below the main html file. If any URL ends
+// in .txt it will be parsed as well so you can nest .txt files. URLs inside a
+// .txt file should be relative to that text file.
+//
+// During startup, for each page found the reportFunction will be called with
+// WebGLTestHarnessModule.TestHarness.reportType.ADD_PAGE and msg will be
+// the URL of the test.
+//
+// Each test is required to call testHarness.reportResults. This is most easily
+// accomplished by storing that value on the main window with
+//
+// window.webglTestHarness = testHarness
+//
+// and then adding these to functions to your tests.
+//
+// function reportTestResultsToHarness(success, msg) {
+// if (window.parent.webglTestHarness) {
+// window.parent.webglTestHarness.reportResults(success, msg);
+// }
+// }
+//
+// function notifyFinishedToHarness() {
+// if (window.parent.webglTestHarness) {
+// window.parent.webglTestHarness.notifyFinished();
+// }
+// }
+//
+// This way your tests will still run without the harness and you can use
+// any testing framework you want.
+//
+// Each test should call reportTestResultsToHarness with true for success if it
+// succeeded and false if it fail followed and any message it wants to
+// associate with the test. If your testing framework supports checking for
+// timeout you can call it with success equal to undefined in that case.
+//
+// To run the tests, call testHarness.runTests(options);
+//
+// For each test run, before the page is loaded the reportFunction will be
+// called with WebGLTestHarnessModule.TestHarness.reportType.START_PAGE and msg
+// will be the URL of the test. You may return false if you want the test to be
+// skipped.
+//
+// For each test completed the reportFunction will be called with
+// with WebGLTestHarnessModule.TestHarness.reportType.TEST_RESULT,
+// success = true on success, false on failure, undefined on timeout
+// and msg is any message the test choose to pass on.
+//
+// When all the tests on the page have finished your page must call
+// notifyFinishedToHarness. If notifyFinishedToHarness is not called
+// the harness will assume the test timed out.
+//
+// When all the tests on a page have finished OR the page as timed out the
+// reportFunction will be called with
+// WebGLTestHarnessModule.TestHarness.reportType.FINISH_PAGE
+// where success = true if the page has completed or undefined if the page timed
+// out.
+//
+// Finally, when all the tests have completed the reportFunction will be called
+// with WebGLTestHarnessModule.TestHarness.reportType.FINISHED_ALL_TESTS.
+//
+// Harness Options
+//
+// These are passed in to the TestHarness as a JavaScript object
+//
+// version: (required!)
+//
+// Specifies a version used to filter tests. Tests marked as requiring
+// a version greater than this version will not be included.
+//
+// example: new TestHarness(...., {version: "3.1.2"});
+//
+// minVersion:
+//
+// Specifies the minimum version a test must require to be included.
+// This basically flips the filter so that only tests marked with
+// --min-version will be included if they are at this minVersion or
+// greater.
+//
+// example: new TestHarness(...., {minVersion: "2.3.1"});
+//
+// maxVersion:
+//
+// Specifies the maximum version a test must require to be included.
+// This basically flips the filter so that only tests marked with
+// --max-version will be included if they are at this maxVersion or
+// less.
+//
+// example: new TestHarness(...., {maxVersion: "2.3.1"});
+//
+// fast:
+//
+// Specifies to skip any tests marked as slow.
+//
+// example: new TestHarness(..., {fast: true});
+//
+// Test Options:
+//
+// Any test URL or .txt file can be prefixed by the following options
+//
+// min-version:
+//
+// Sets the minimum version required to include this test. A version is
+// passed into the harness options. Any test marked as requiring a
+// min-version greater than the version passed to the harness is skipped.
+// This allows you to add new tests to a suite of tests for a future
+// version of the suite without including the test in the current version.
+// If no -min-version is specified it is inheriited from the .txt file
+// including it. The default is 1.0.0
+//
+// example: --min-version 2.1.3 sometest.html
+//
+// max-version:
+//
+// Sets the maximum version required to include this test. A version is
+// passed into the harness options. Any test marked as requiring a
+// max-version less than the version passed to the harness is skipped.
+// This allows you to test functionality that has been removed from later
+// versions of the suite.
+// If no -max-version is specified it is inherited from the .txt file
+// including it.
+//
+// example: --max-version 1.9.9 sometest.html
+//
+// slow:
+//
+// Marks a test as slow. Slow tests can be skipped by passing fastOnly: true
+// to the TestHarness. Of course you need to pass all tests but sometimes
+// you'd like to test quickly and run only the fast subset of tests.
+//
+// example: --slow some-test-that-takes-2-mins.html
+//
+
+WebGLTestHarnessModule = function() {
+
+/**
+ * Wrapped logging function.
+ */
+var log = function(msg) {
+ if (window.console && window.console.log) {
+ window.console.log(msg);
+ }
+};
+
+/**
+ * Loads text from an external file. This function is synchronous.
+ * @param {string} url The url of the external file.
+ * @param {!function(bool, string): void} callback that is sent a bool for
+ * success and the string.
+ */
+var loadTextFileAsynchronous = function(url, callback) {
+ log ("loading: " + url);
+ var error = 'loadTextFileSynchronous failed to load url "' + url + '"';
+ var request;
+ if (window.XMLHttpRequest) {
+ request = new XMLHttpRequest();
+ if (request.overrideMimeType) {
+ request.overrideMimeType('text/plain');
+ }
+ } else {
+ throw 'XMLHttpRequest is disabled';
+ }
+ try {
+ request.open('GET', url, true);
+ request.onreadystatechange = function() {
+ if (request.readyState == 4) {
+ var text = '';
+ // HTTP reports success with a 200 status. The file protocol reports
+ // success with zero. HTTP does not use zero as a status code (they
+ // start at 100).
+ // https://developer.mozilla.org/En/Using_XMLHttpRequest
+ var success = request.status == 200 || request.status == 0;
+ if (success) {
+ text = request.responseText;
+ }
+ log("loaded: " + url);
+ callback(success, text);
+ }
+ };
+ request.send(null);
+ } catch (e) {
+ log("failed to load: " + url);
+ callback(false, '');
+ }
+};
+
+/**
+ * @param {string} versionString WebGL version string.
+ * @return {number} Integer containing the WebGL major version.
+ */
+var getMajorVersion = function(versionString) {
+ if (!versionString) {
+ return 1;
+ }
+ return parseInt(versionString.split(" ")[0].split(".")[0], 10);
+};
+
+/**
+ * @param {string} url Base URL of the test.
+ * @param {map} options Map of options to append to the URL's query string.
+ * @return {string} URL that will run the test with the given WebGL version.
+ */
+var getURLWithOptions = function(url, options) {
+ var queryArgs = 0;
+
+ for (i in options) {
+ url += queryArgs ? "&" : "?";
+ url += i + "=" + options[i];
+ queryArgs++;
+ }
+
+ return url;
+};
+
+/**
+ * Compare version strings.
+ */
+var greaterThanOrEqualToVersion = function(have, want) {
+ have = have.split(" ")[0].split(".");
+ want = want.split(" ")[0].split(".");
+
+ //have 1.2.3 want 1.1
+ //have 1.1.1 want 1.1
+ //have 1.0.9 want 1.1
+ //have 1.1 want 1.1.1
+
+ for (var ii = 0; ii < want.length; ++ii) {
+ var wantNum = parseInt(want[ii]);
+ var haveNum = have[ii] ? parseInt(have[ii]) : 0
+ if (haveNum > wantNum) {
+ return true; // 2.0.0 is greater than 1.2.3
+ }
+ if (haveNum < wantNum) {
+ return false;
+ }
+ }
+ return true;
+};
+
+/**
+ * Reads a file, recursively adding files referenced inside.
+ *
+ * Each line of URL is parsed, comments starting with '#' or ';'
+ * or '//' are stripped.
+ *
+ * arguments beginning with -- are extracted
+ *
+ * lines that end in .txt are recursively scanned for more files
+ * other lines are added to the list of files.
+ *
+ * @param {string} url The url of the file to read.
+ * @param {function(boolean, !Array.<string>):void} callback
+ * Callback that is called with true for success and an
+ * array of filenames.
+ * @param {Object} options Optional options
+ *
+ * Options:
+ * version: {string} The version of the conformance test.
+ * Tests with the argument --min-version <version> will
+ * be ignored version is less then <version>
+ *
+ */
+var getFileList = function(url, callback, options) {
+ var files = [];
+
+ var copyObject = function(obj) {
+ return JSON.parse(JSON.stringify(obj));
+ };
+
+ var toCamelCase = function(str) {
+ return str.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase() });
+ };
+
+ var globalOptions = copyObject(options);
+ globalOptions.defaultVersion = "1.0";
+ globalOptions.defaultMaxVersion = null;
+
+ var getFileListImpl = function(prefix, line, lineNum, hierarchicalOptions, callback) {
+ var files = [];
+
+ var args = line.split(/\s+/);
+ var nonOptions = [];
+ var useTest = true;
+ var testOptions = {};
+ for (var jj = 0; jj < args.length; ++jj) {
+ var arg = args[jj];
+ if (arg[0] == '-') {
+ if (arg[1] != '-') {
+ throw ("bad option at in " + url + ":" + lineNum + ": " + arg);
+ }
+ var option = arg.substring(2);
+ switch (option) {
+ // no argument options.
+ case 'slow':
+ testOptions[toCamelCase(option)] = true;
+ break;
+ // one argument options.
+ case 'min-version':
+ case 'max-version':
+ ++jj;
+ testOptions[toCamelCase(option)] = args[jj];
+ break;
+ default:
+ throw ("bad unknown option '" + option + "' at in " + url + ":" + lineNum + ": " + arg);
+ }
+ } else {
+ nonOptions.push(arg);
+ }
+ }
+ var url = prefix + nonOptions.join(" ");
+
+ if (url.substr(url.length - 4) != '.txt') {
+ var minVersion = testOptions.minVersion;
+ if (!minVersion) {
+ minVersion = hierarchicalOptions.defaultVersion;
+ }
+ var maxVersion = testOptions.maxVersion;
+ if (!maxVersion) {
+ maxVersion = hierarchicalOptions.defaultMaxVersion;
+ }
+ var slow = testOptions.slow;
+ if (!slow) {
+ slow = hierarchicalOptions.defaultSlow;
+ }
+
+ if (globalOptions.fast && slow) {
+ useTest = false;
+ } else if (globalOptions.minVersion) {
+ useTest = greaterThanOrEqualToVersion(minVersion, globalOptions.minVersion);
+ } else if (globalOptions.maxVersion && maxVersion) {
+ useTest = greaterThanOrEqualToVersion(globalOptions.maxVersion, maxVersion);
+ } else {
+ useTest = greaterThanOrEqualToVersion(globalOptions.version, minVersion);
+ if (maxVersion) {
+ useTest = useTest && greaterThanOrEqualToVersion(maxVersion, globalOptions.version);
+ }
+ }
+ }
+
+ if (!useTest) {
+ callback(true, []);
+ return;
+ }
+
+ if (url.substr(url.length - 4) == '.txt') {
+ // If a version was explicity specified pass it down.
+ if (testOptions.minVersion) {
+ hierarchicalOptions.defaultVersion = testOptions.minVersion;
+ }
+ if (testOptions.maxVersion) {
+ hierarchicalOptions.defaultMaxVersion = testOptions.maxVersion;
+ }
+ if (testOptions.slow) {
+ hierarchicalOptions.defaultSlow = testOptions.slow;
+ }
+ loadTextFileAsynchronous(url, function() {
+ return function(success, text) {
+ if (!success) {
+ callback(false, '');
+ return;
+ }
+ var lines = text.split('\n');
+ var prefix = '';
+ var lastSlash = url.lastIndexOf('/');
+ if (lastSlash >= 0) {
+ prefix = url.substr(0, lastSlash + 1);
+ }
+ var fail = false;
+ var count = 1;
+ var index = 0;
+ for (var ii = 0; ii < lines.length; ++ii) {
+ var str = lines[ii].replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+ if (str.length > 4 &&
+ str[0] != '#' &&
+ str[0] != ";" &&
+ str.substr(0, 2) != "//") {
+ ++count;
+ getFileListImpl(prefix, str, ii + 1, copyObject(hierarchicalOptions), function(index) {
+ return function(success, new_files) {
+ //log("got files: " + new_files.length);
+ if (success) {
+ files[index] = new_files;
+ }
+ finish(success);
+ };
+ }(index++));
+ }
+ }
+ finish(true);
+
+ function finish(success) {
+ if (!success) {
+ fail = true;
+ }
+ --count;
+ //log("count: " + count);
+ if (!count) {
+ callback(!fail, files);
+ }
+ }
+ }
+ }());
+ } else {
+ files.push(url);
+ callback(true, files);
+ }
+ };
+
+ getFileListImpl('', url, 1, globalOptions, function(success, files) {
+ // flatten
+ var flat = [];
+ flatten(files);
+ function flatten(files) {
+ for (var ii = 0; ii < files.length; ++ii) {
+ var value = files[ii];
+ if (typeof(value) == "string") {
+ flat.push(value);
+ } else {
+ flatten(value);
+ }
+ }
+ }
+ callback(success, flat);
+ });
+};
+
+var FilterURL = (function() {
+ var prefix = window.location.pathname;
+ prefix = prefix.substring(0, prefix.lastIndexOf("/") + 1);
+ return function(url) {
+ if (url.substring(0, prefix.length) == prefix) {
+ url = url.substring(prefix.length);
+ }
+ return url;
+ };
+}());
+
+var TestFile = function(url) {
+ this.url = url;
+};
+
+var Test = function(file) {
+ this.file = file;
+};
+
+var TestHarness = function(iframe, filelistUrl, reportFunc, options) {
+ this.window = window;
+ this.iframes = iframe.length ? iframe : [iframe];
+ this.reportFunc = reportFunc;
+ this.timeoutDelay = 20000;
+ this.files = [];
+ this.allowSkip = options.allowSkip;
+ this.webglVersion = getMajorVersion(options.version);
+ this.dumpShaders = options.dumpShaders;
+ this.quiet = options.quiet;
+
+ var that = this;
+ getFileList(filelistUrl, function() {
+ return function(success, files) {
+ that.addFiles_(success, files);
+ };
+ }(), options);
+
+};
+
+TestHarness.reportType = {
+ ADD_PAGE: 1,
+ READY: 2,
+ START_PAGE: 3,
+ TEST_RESULT: 4,
+ FINISH_PAGE: 5,
+ FINISHED_ALL_TESTS: 6
+};
+
+TestHarness.prototype.addFiles_ = function(success, files) {
+ if (!success) {
+ this.reportFunc(
+ TestHarness.reportType.FINISHED_ALL_TESTS,
+ '',
+ 'Unable to load tests. Are you running locally?\n' +
+ 'You need to run from a server or configure your\n' +
+ 'browser to allow access to local files (not recommended).\n\n' +
+ 'Note: An easy way to run from a server:\n\n' +
+ '\tcd path_to_tests\n' +
+ '\tpython -m SimpleHTTPServer\n\n' +
+ 'then point your browser to ' +
+ '<a href="http://localhost:8000/webgl-conformance-tests.html">' +
+ 'http://localhost:8000/webgl-conformance-tests.html</a>',
+ false)
+ return;
+ }
+ log("total files: " + files.length);
+ for (var ii = 0; ii < files.length; ++ii) {
+ log("" + ii + ": " + files[ii]);
+ this.files.push(new TestFile(files[ii]));
+ this.reportFunc(TestHarness.reportType.ADD_PAGE, '', files[ii], undefined);
+ }
+ this.reportFunc(TestHarness.reportType.READY, '', undefined, undefined);
+}
+
+TestHarness.prototype.runTests = function(opt_options) {
+ var options = opt_options || { };
+ options.start = options.start || 0;
+ options.count = options.count || this.files.length;
+
+ this.idleIFrames = this.iframes.slice(0);
+ this.runningTests = {};
+ var testsToRun = [];
+ for (var ii = 0; ii < options.count; ++ii) {
+ testsToRun.push(ii + options.start);
+ }
+ this.numTestsRemaining = options.count;
+ this.testsToRun = testsToRun;
+ this.startNextTest();
+};
+
+TestHarness.prototype.setTimeout = function(test) {
+ var that = this;
+ test.timeoutId = this.window.setTimeout(function() {
+ that.timeout(test);
+ }, this.timeoutDelay);
+};
+
+TestHarness.prototype.clearTimeout = function(test) {
+ this.window.clearTimeout(test.timeoutId);
+};
+
+TestHarness.prototype.startNextTest = function() {
+ if (this.numTestsRemaining == 0) {
+ log("done");
+ this.reportFunc(TestHarness.reportType.FINISHED_ALL_TESTS,
+ '', '', true);
+ } else {
+ while (this.testsToRun.length > 0 && this.idleIFrames.length > 0) {
+ var testId = this.testsToRun.shift();
+ var iframe = this.idleIFrames.shift();
+ this.startTest(iframe, this.files[testId], this.webglVersion);
+ }
+ }
+};
+
+TestHarness.prototype.startTest = function(iframe, testFile, webglVersion) {
+ var test = {
+ iframe: iframe,
+ testFile: testFile
+ };
+ var url = testFile.url;
+ this.runningTests[url] = test;
+ log("loading: " + url);
+ if (this.reportFunc(TestHarness.reportType.START_PAGE, url, url, undefined)) {
+ iframe.src = getURLWithOptions(url, {
+ "webglVersion": webglVersion,
+ "dumpShaders": this.dumpShaders,
+ "quiet": this.quiet
+ });
+ this.setTimeout(test);
+ } else {
+ this.reportResults(url, !!this.allowSkip, "skipped", true);
+ this.notifyFinished(url);
+ }
+};
+
+TestHarness.prototype.getTest = function(url) {
+ var test = this.runningTests[FilterURL(url)];
+ if (!test) {
+ throw("unknown test:" + url);
+ }
+ return test;
+};
+
+TestHarness.prototype.reportResults = function(url, success, msg, skipped) {
+ url = FilterURL(url);
+ var test = this.getTest(url);
+ this.clearTimeout(test);
+ log(success ? "PASS" : "FAIL", msg);
+ this.reportFunc(TestHarness.reportType.TEST_RESULT, url, msg, success, skipped);
+ // For each result we get, reset the timeout
+ this.setTimeout(test);
+};
+
+TestHarness.prototype.dequeTest = function(test) {
+ this.clearTimeout(test);
+ this.idleIFrames.push(test.iframe);
+ delete this.runningTests[test.testFile.url];
+ --this.numTestsRemaining;
+}
+
+TestHarness.prototype.notifyFinished = function(url) {
+ url = FilterURL(url);
+ var test = this.getTest(url);
+ log(url + ": finished");
+ this.dequeTest(test);
+ this.reportFunc(TestHarness.reportType.FINISH_PAGE, url, url, true);
+ this.startNextTest();
+};
+
+TestHarness.prototype.timeout = function(test) {
+ this.dequeTest(test);
+ var url = test.testFile.url;
+ log(url + ": timeout");
+ this.reportFunc(TestHarness.reportType.FINISH_PAGE, url, url, undefined);
+ this.startNextTest();
+};
+
+TestHarness.prototype.setTimeoutDelay = function(x) {
+ this.timeoutDelay = x;
+};
+
+return {
+ 'TestHarness': TestHarness,
+ 'getMajorVersion': getMajorVersion,
+ 'getURLWithOptions': getURLWithOptions
+ };
+
+}();
+
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js b/dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js
new file mode 100644
index 000000000..545ccaed5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js
@@ -0,0 +1,3122 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+var WebGLTestUtils = (function() {
+"use strict";
+
+/**
+ * Wrapped logging function.
+ * @param {string} msg The message to log.
+ */
+var log = function(msg) {
+ bufferedLogToConsole(msg);
+};
+
+/**
+ * Wrapped logging function.
+ * @param {string} msg The message to log.
+ */
+var error = function(msg) {
+ // For the time being, diverting this to window.console.log rather
+ // than window.console.error. If anyone cares enough they can
+ // generalize the mechanism in js-test-pre.js.
+ log(msg);
+};
+
+/**
+ * Turn off all logging.
+ */
+var loggingOff = function() {
+ log = function() {};
+ error = function() {};
+};
+
+/**
+ * Converts a WebGL enum to a string.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} value The enum value.
+ * @return {string} The enum as a string.
+ */
+var glEnumToString = function(gl, value) {
+ // Optimization for the most common enum:
+ if (value === gl.NO_ERROR) {
+ return "NO_ERROR";
+ }
+ for (var p in gl) {
+ if (gl[p] == value) {
+ if (p == 'drawingBufferWidth' || p == 'drawingBufferHeight') {
+ continue;
+ }
+ return p;
+ }
+ }
+ return "0x" + Number(value).toString(16);
+};
+
+var lastError = "";
+
+/**
+ * Returns the last compiler/linker error.
+ * @return {string} The last compiler/linker error.
+ */
+var getLastError = function() {
+ return lastError;
+};
+
+/**
+ * Whether a haystack ends with a needle.
+ * @param {string} haystack String to search
+ * @param {string} needle String to search for.
+ * @param {boolean} True if haystack ends with needle.
+ */
+var endsWith = function(haystack, needle) {
+ return haystack.substr(haystack.length - needle.length) === needle;
+};
+
+/**
+ * Whether a haystack starts with a needle.
+ * @param {string} haystack String to search
+ * @param {string} needle String to search for.
+ * @param {boolean} True if haystack starts with needle.
+ */
+var startsWith = function(haystack, needle) {
+ return haystack.substr(0, needle.length) === needle;
+};
+
+/**
+ * A vertex shader for a single texture.
+ * @type {string}
+ */
+var simpleTextureVertexShader = [
+ 'attribute vec4 vPosition;',
+ 'attribute vec2 texCoord0;',
+ 'varying vec2 texCoord;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ ' texCoord = texCoord0;',
+ '}'].join('\n');
+
+/**
+ * A fragment shader for a single texture.
+ * @type {string}
+ */
+var simpleTextureFragmentShader = [
+ 'precision mediump float;',
+ 'uniform sampler2D tex;',
+ 'varying vec2 texCoord;',
+ 'void main() {',
+ ' gl_FragData[0] = texture2D(tex, texCoord);',
+ '}'].join('\n');
+
+/**
+ * A fragment shader for a single cube map texture.
+ * @type {string}
+ */
+var simpleCubeMapTextureFragmentShader = [
+ 'precision mediump float;',
+ 'uniform samplerCube tex;',
+ 'uniform int face;',
+ 'varying vec2 texCoord;',
+ 'void main() {',
+ // Transform [0, 1] -> [-1, 1]
+ ' vec2 texC2 = (texCoord * 2.) - 1.;',
+ // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord.
+ ' vec3 texCube = vec3(0., 0., 0.);',
+ ' if (face == 34069) {', // TEXTURE_CUBE_MAP_POSITIVE_X
+ ' texCube = vec3(1., -texC2.y, -texC2.x);',
+ ' } else if (face == 34070) {', // TEXTURE_CUBE_MAP_NEGATIVE_X
+ ' texCube = vec3(-1., -texC2.y, texC2.x);',
+ ' } else if (face == 34071) {', // TEXTURE_CUBE_MAP_POSITIVE_Y
+ ' texCube = vec3(texC2.x, 1., texC2.y);',
+ ' } else if (face == 34072) {', // TEXTURE_CUBE_MAP_NEGATIVE_Y
+ ' texCube = vec3(texC2.x, -1., -texC2.y);',
+ ' } else if (face == 34073) {', // TEXTURE_CUBE_MAP_POSITIVE_Z
+ ' texCube = vec3(texC2.x, -texC2.y, 1.);',
+ ' } else if (face == 34074) {', // TEXTURE_CUBE_MAP_NEGATIVE_Z
+ ' texCube = vec3(-texC2.x, -texC2.y, -1.);',
+ ' }',
+ ' gl_FragData[0] = textureCube(tex, texCube);',
+ '}'].join('\n');
+
+/**
+ * A vertex shader for a single texture.
+ * @type {string}
+ */
+var noTexCoordTextureVertexShader = [
+ 'attribute vec4 vPosition;',
+ 'varying vec2 texCoord;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ ' texCoord = vPosition.xy * 0.5 + 0.5;',
+ '}'].join('\n');
+
+/**
+ * A vertex shader for a uniform color.
+ * @type {string}
+ */
+var simpleVertexShader = [
+ 'attribute vec4 vPosition;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ '}'].join('\n');
+
+/**
+ * A fragment shader for a uniform color.
+ * @type {string}
+ */
+var simpleColorFragmentShader = [
+ 'precision mediump float;',
+ 'uniform vec4 u_color;',
+ 'void main() {',
+ ' gl_FragData[0] = u_color;',
+ '}'].join('\n');
+
+/**
+ * A vertex shader for vertex colors.
+ * @type {string}
+ */
+var simpleVertexColorVertexShader = [
+ 'attribute vec4 vPosition;',
+ 'attribute vec4 a_color;',
+ 'varying vec4 v_color;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ ' v_color = a_color;',
+ '}'].join('\n');
+
+/**
+ * A fragment shader for vertex colors.
+ * @type {string}
+ */
+var simpleVertexColorFragmentShader = [
+ 'precision mediump float;',
+ 'varying vec4 v_color;',
+ 'void main() {',
+ ' gl_FragData[0] = v_color;',
+ '}'].join('\n');
+
+/**
+ * Creates a program, attaches shaders, binds attrib locations, links the
+ * program and calls useProgram.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<!WebGLShader|string>} shaders The shaders to
+ * attach, or the source, or the id of a script to get
+ * the source from.
+ * @param {!Array.<string>} opt_attribs The attribs names.
+ * @param {!Array.<number>} opt_locations The locations for the attribs.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ */
+var setupProgram = function(
+ gl, shaders, opt_attribs, opt_locations, opt_logShaders) {
+ var realShaders = [];
+ var program = gl.createProgram();
+ var shaderCount = 0;
+ for (var ii = 0; ii < shaders.length; ++ii) {
+ var shader = shaders[ii];
+ var shaderType = undefined;
+ if (typeof shader == 'string') {
+ var element = document.getElementById(shader);
+ if (element) {
+ if (element.type != "x-shader/x-vertex" && element.type != "x-shader/x-fragment")
+ shaderType = ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER;
+ shader = loadShaderFromScript(gl, shader, shaderType, undefined, opt_logShaders);
+ } else if (endsWith(shader, ".vert")) {
+ shader = loadShaderFromFile(gl, shader, gl.VERTEX_SHADER, undefined, opt_logShaders);
+ } else if (endsWith(shader, ".frag")) {
+ shader = loadShaderFromFile(gl, shader, gl.FRAGMENT_SHADER, undefined, opt_logShaders);
+ } else {
+ shader = loadShader(gl, shader, ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER, undefined, opt_logShaders);
+ }
+ } else if (opt_logShaders) {
+ throw 'Shader source logging requested but no shader source provided';
+ }
+ if (shader) {
+ ++shaderCount;
+ gl.attachShader(program, shader);
+ }
+ }
+ if (shaderCount != 2) {
+ error("Error in compiling shader");
+ return null;
+ }
+ if (opt_attribs) {
+ for (var ii = 0; ii < opt_attribs.length; ++ii) {
+ gl.bindAttribLocation(
+ program,
+ opt_locations ? opt_locations[ii] : ii,
+ opt_attribs[ii]);
+ }
+ }
+ gl.linkProgram(program);
+
+ // Check the link status
+ var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+ if (!linked) {
+ // something went wrong with the link
+ lastError = gl.getProgramInfoLog (program);
+ error("Error in program linking:" + lastError);
+
+ gl.deleteProgram(program);
+ return null;
+ }
+
+ gl.useProgram(program);
+ return program;
+};
+
+/**
+ * Creates a program, attaches shader, sets up trasnform feedback varyings,
+ * binds attrib locations, links the program and calls useProgram.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<!WebGLShader|string>} shaders The shaders to
+ * attach, or the source, or the id of a script to get
+ * the source from.
+ * @param {!Array.<string>} varyings The transform feedback varying names.
+ * @param {number} bufferMode The mode used to capture the varying variables.
+ * @param {!Array.<string>} opt_attribs The attribs names.
+ * @param {!Array.<number>} opt_locations The locations for the attribs.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ */
+var setupTransformFeedbackProgram = function(
+ gl, shaders, varyings, bufferMode, opt_attribs, opt_locations, opt_logShaders) {
+ var realShaders = [];
+ var program = gl.createProgram();
+ var shaderCount = 0;
+ for (var ii = 0; ii < shaders.length; ++ii) {
+ var shader = shaders[ii];
+ var shaderType = undefined;
+ if (typeof shader == 'string') {
+ var element = document.getElementById(shader);
+ if (element) {
+ if (element.type != "x-shader/x-vertex" && element.type != "x-shader/x-fragment")
+ shaderType = ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER;
+ shader = loadShaderFromScript(gl, shader, shaderType, undefined, opt_logShaders);
+ } else if (endsWith(shader, ".vert")) {
+ shader = loadShaderFromFile(gl, shader, gl.VERTEX_SHADER, undefined, opt_logShaders);
+ } else if (endsWith(shader, ".frag")) {
+ shader = loadShaderFromFile(gl, shader, gl.FRAGMENT_SHADER, undefined, opt_logShaders);
+ } else {
+ shader = loadShader(gl, shader, ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER, undefined, opt_logShaders);
+ }
+ } else if (opt_logShaders) {
+ throw 'Shader source logging requested but no shader source provided';
+ }
+ if (shader) {
+ ++shaderCount;
+ gl.attachShader(program, shader);
+ }
+ }
+ if (shaderCount != 2) {
+ error("Error in compiling shader");
+ return null;
+ }
+
+ if (opt_attribs) {
+ for (var ii = 0; ii < opt_attribs.length; ++ii) {
+ gl.bindAttribLocation(
+ program,
+ opt_locations ? opt_locations[ii] : ii,
+ opt_attribs[ii]);
+ }
+ }
+
+ gl.transformFeedbackVaryings(program, varyings, bufferMode);
+
+ gl.linkProgram(program);
+
+ // Check the link status
+ var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+ if (!linked) {
+ // something went wrong with the link
+ lastError = gl.getProgramInfoLog (program);
+ error("Error in program linking:" + lastError);
+
+ gl.deleteProgram(program);
+ return null;
+ }
+
+ gl.useProgram(program);
+ return program;
+};
+
+/**
+ * Creates a simple texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {WebGLProgram}
+ */
+var setupNoTexCoordTextureProgram = function(gl) {
+ return setupProgram(gl,
+ [noTexCoordTextureVertexShader, simpleTextureFragmentShader],
+ ['vPosition'],
+ [0]);
+};
+
+/**
+ * Creates a simple texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+var setupSimpleTextureProgram = function(
+ gl, opt_positionLocation, opt_texcoordLocation) {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ return setupProgram(gl,
+ [simpleTextureVertexShader, simpleTextureFragmentShader],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+};
+
+/**
+ * Creates a simple cube map texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+var setupSimpleCubeMapTextureProgram = function(
+ gl, opt_positionLocation, opt_texcoordLocation) {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ return setupProgram(gl,
+ [simpleTextureVertexShader, simpleCubeMapTextureFragmentShader],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+};
+
+/**
+ * Creates a simple vertex color program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_vertexColorLocation The attrib location
+ * for vertex colors.
+ * @return {WebGLProgram}
+ */
+var setupSimpleVertexColorProgram = function(
+ gl, opt_positionLocation, opt_vertexColorLocation) {
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_vertexColorLocation = opt_vertexColorLocation || 1;
+ return setupProgram(gl,
+ [simpleVertexColorVertexShader, simpleVertexColorFragmentShader],
+ ['vPosition', 'a_color'],
+ [opt_positionLocation, opt_vertexColorLocation]);
+};
+
+/**
+ * Creates a simple color program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @return {WebGLProgram}
+ */
+var setupSimpleColorProgram = function(gl, opt_positionLocation) {
+ opt_positionLocation = opt_positionLocation || 0;
+ return setupProgram(gl,
+ [simpleVertexShader, simpleColorFragmentShader],
+ ['vPosition'],
+ [opt_positionLocation]);
+};
+
+/**
+ * Creates buffers for a textured unit quad and attaches them to vertex attribs.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {!Array.<WebGLBuffer>} The buffer objects that were
+ * created.
+ */
+var setupUnitQuad = function(gl, opt_positionLocation, opt_texcoordLocation) {
+ return setupUnitQuadWithTexCoords(gl, [ 0.0, 0.0 ], [ 1.0, 1.0 ],
+ opt_positionLocation, opt_texcoordLocation);
+};
+
+/**
+ * Creates buffers for a textured unit quad with specified lower left
+ * and upper right texture coordinates, and attaches them to vertex
+ * attribs.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} lowerLeftTexCoords The texture coordinates for the lower left corner.
+ * @param {!Array.<number>} upperRightTexCoords The texture coordinates for the upper right corner.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {!Array.<WebGLBuffer>} The buffer objects that were
+ * created.
+ */
+var setupUnitQuadWithTexCoords = function(
+ gl, lowerLeftTexCoords, upperRightTexCoords,
+ opt_positionLocation, opt_texcoordLocation) {
+ return setupQuad(gl, {
+ positionLocation: opt_positionLocation || 0,
+ texcoordLocation: opt_texcoordLocation || 1,
+ lowerLeftTexCoords: lowerLeftTexCoords,
+ upperRightTexCoords: upperRightTexCoords
+ });
+};
+
+/**
+ * Makes a quad with various options.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Object} options
+ *
+ * scale: scale to multiple unit quad values by. default 1.0.
+ * positionLocation: attribute location for position.
+ * texcoordLocation: attribute location for texcoords.
+ * If this does not exist no texture coords are created.
+ * lowerLeftTexCoords: an array of 2 values for the
+ * lowerLeftTexCoords.
+ * upperRightTexCoords: an array of 2 values for the
+ * upperRightTexCoords.
+ */
+var setupQuad = function(gl, options) {
+ var positionLocation = options.positionLocation || 0;
+ var scale = options.scale || 1;
+
+ var objects = [];
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0 * scale , 1.0 * scale,
+ -1.0 * scale , 1.0 * scale,
+ -1.0 * scale , -1.0 * scale,
+ 1.0 * scale , 1.0 * scale,
+ -1.0 * scale , -1.0 * scale,
+ 1.0 * scale , -1.0 * scale]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(positionLocation);
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
+ objects.push(vertexObject);
+
+ if (options.texcoordLocation !== undefined) {
+ var llx = options.lowerLeftTexCoords[0];
+ var lly = options.lowerLeftTexCoords[1];
+ var urx = options.upperRightTexCoords[0];
+ var ury = options.upperRightTexCoords[1];
+
+ vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ urx, ury,
+ llx, ury,
+ llx, lly,
+ urx, ury,
+ llx, lly,
+ urx, lly]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(options.texcoordLocation);
+ gl.vertexAttribPointer(options.texcoordLocation, 2, gl.FLOAT, false, 0, 0);
+ objects.push(vertexObject);
+ }
+
+ return objects;
+};
+
+/**
+ * Creates a program and buffers for rendering a textured quad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for
+ * position. Default = 0.
+ * @param {number} opt_texcoordLocation The attrib location for
+ * texture coords. Default = 1.
+ * @return {!WebGLProgram}
+ */
+var setupTexturedQuad = function(
+ gl, opt_positionLocation, opt_texcoordLocation) {
+ var program = setupSimpleTextureProgram(
+ gl, opt_positionLocation, opt_texcoordLocation);
+ setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation);
+ return program;
+};
+
+/**
+ * Creates a program and buffers for rendering a color quad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @return {!WebGLProgram}
+ */
+var setupColorQuad = function(gl, opt_positionLocation) {
+ opt_positionLocation = opt_positionLocation || 0;
+ var program = setupSimpleColorProgram(gl);
+ setupUnitQuad(gl, opt_positionLocation);
+ return program;
+};
+
+/**
+ * Creates a program and buffers for rendering a textured quad with
+ * specified lower left and upper right texture coordinates.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} lowerLeftTexCoords The texture coordinates for the lower left corner.
+ * @param {!Array.<number>} upperRightTexCoords The texture coordinates for the upper right corner.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {!WebGLProgram}
+ */
+var setupTexturedQuadWithTexCoords = function(
+ gl, lowerLeftTexCoords, upperRightTexCoords,
+ opt_positionLocation, opt_texcoordLocation) {
+ var program = setupSimpleTextureProgram(
+ gl, opt_positionLocation, opt_texcoordLocation);
+ setupUnitQuadWithTexCoords(gl, lowerLeftTexCoords, upperRightTexCoords,
+ opt_positionLocation, opt_texcoordLocation);
+ return program;
+};
+
+/**
+ * Creates a program and buffers for rendering a textured quad with
+ * a cube map texture.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for
+ * position. Default = 0.
+ * @param {number} opt_texcoordLocation The attrib location for
+ * texture coords. Default = 1.
+ * @return {!WebGLProgram}
+ */
+var setupTexturedQuadWithCubeMap = function(
+ gl, opt_positionLocation, opt_texcoordLocation) {
+ var program = setupSimpleCubeMapTextureProgram(
+ gl, opt_positionLocation, opt_texcoordLocation);
+ setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation);
+ return program;
+};
+
+/**
+ * Creates a unit quad with only positions of a given resolution.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} gridRes The resolution of the mesh grid,
+ * expressed in the number of quads across and down.
+ * @param {number} opt_positionLocation The attrib location for position.
+ */
+var setupIndexedQuad = function (
+ gl, gridRes, opt_positionLocation, opt_flipOddTriangles) {
+ return setupIndexedQuadWithOptions(gl,
+ { gridRes: gridRes,
+ positionLocation: opt_positionLocation,
+ flipOddTriangles: opt_flipOddTriangles
+ });
+};
+
+/**
+ * Creates a quad with various options.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Object} options The options. See below.
+ * @return {!Array.<WebGLBuffer>} The created buffers.
+ * [positions, <colors>, indices]
+ *
+ * Options:
+ * gridRes: number of quads across and down grid.
+ * positionLocation: attrib location for position
+ * flipOddTriangles: reverse order of vertices of every other
+ * triangle
+ * positionOffset: offset added to each vertex
+ * positionMult: multipier for each vertex
+ * colorLocation: attrib location for vertex colors. If
+ * undefined no vertex colors will be created.
+ */
+var setupIndexedQuadWithOptions = function (gl, options) {
+ var positionLocation = options.positionLocation || 0;
+ var objects = [];
+
+ var gridRes = options.gridRes || 1;
+ var positionOffset = options.positionOffset || 0;
+ var positionMult = options.positionMult || 1;
+ var vertsAcross = gridRes + 1;
+ var numVerts = vertsAcross * vertsAcross;
+ var positions = new Float32Array(numVerts * 3);
+ var indices = new Uint16Array(6 * gridRes * gridRes);
+ var poffset = 0;
+
+ for (var yy = 0; yy <= gridRes; ++yy) {
+ for (var xx = 0; xx <= gridRes; ++xx) {
+ positions[poffset + 0] = (-1 + 2 * xx / gridRes) * positionMult + positionOffset;
+ positions[poffset + 1] = (-1 + 2 * yy / gridRes) * positionMult + positionOffset;
+ positions[poffset + 2] = 0;
+
+ poffset += 3;
+ }
+ }
+
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(positionLocation);
+ gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
+ objects.push(buf);
+
+ if (options.colorLocation !== undefined) {
+ var colors = new Float32Array(numVerts * 4);
+ for (var yy = 0; yy <= gridRes; ++yy) {
+ for (var xx = 0; xx <= gridRes; ++xx) {
+ if (options.color !== undefined) {
+ colors[poffset + 0] = options.color[0];
+ colors[poffset + 1] = options.color[1];
+ colors[poffset + 2] = options.color[2];
+ colors[poffset + 3] = options.color[3];
+ } else {
+ colors[poffset + 0] = xx / gridRes;
+ colors[poffset + 1] = yy / gridRes;
+ colors[poffset + 2] = (xx / gridRes) * (yy / gridRes);
+ colors[poffset + 3] = (yy % 2) * 0.5 + 0.5;
+ }
+ poffset += 4;
+ }
+ }
+
+ buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(options.colorLocation);
+ gl.vertexAttribPointer(options.colorLocation, 4, gl.FLOAT, false, 0, 0);
+ objects.push(buf);
+ }
+
+ var tbase = 0;
+ for (var yy = 0; yy < gridRes; ++yy) {
+ var index = yy * vertsAcross;
+ for (var xx = 0; xx < gridRes; ++xx) {
+ indices[tbase + 0] = index + 0;
+ indices[tbase + 1] = index + 1;
+ indices[tbase + 2] = index + vertsAcross;
+ indices[tbase + 3] = index + vertsAcross;
+ indices[tbase + 4] = index + 1;
+ indices[tbase + 5] = index + vertsAcross + 1;
+
+ if (options.flipOddTriangles) {
+ indices[tbase + 4] = index + vertsAcross + 1;
+ indices[tbase + 5] = index + 1;
+ }
+
+ index += 1;
+ tbase += 6;
+ }
+ }
+
+ buf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+ objects.push(buf);
+
+ return objects;
+};
+
+/**
+ * Returns the constructor for a typed array that corresponds to the given
+ * WebGL type.
+ * @param {!WebGLRenderingContext} gl A WebGLRenderingContext.
+ * @param {number} type The WebGL type (eg, gl.UNSIGNED_BYTE)
+ * @return {!Constructor} The typed array constructor that
+ * corresponds to the given type.
+ */
+var glTypeToTypedArrayType = function(gl, type) {
+ switch (type) {
+ case gl.BYTE:
+ return window.Int8Array;
+ case gl.UNSIGNED_BYTE:
+ return window.Uint8Array;
+ case gl.SHORT:
+ return window.Int16Array;
+ case gl.UNSIGNED_SHORT:
+ case gl.UNSIGNED_SHORT_5_6_5:
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ return window.Uint16Array;
+ case gl.INT:
+ return window.Int32Array;
+ case gl.UNSIGNED_INT:
+ return window.Uint32Array;
+ default:
+ throw 'unknown gl type ' + glEnumToString(gl, type);
+ }
+};
+
+/**
+ * Returns the number of bytes per component for a given WebGL type.
+ * @param {!WebGLRenderingContext} gl A WebGLRenderingContext.
+ * @param {GLenum} type The WebGL type (eg, gl.UNSIGNED_BYTE)
+ * @return {number} The number of bytes per component.
+ */
+var getBytesPerComponent = function(gl, type) {
+ switch (type) {
+ case gl.BYTE:
+ case gl.UNSIGNED_BYTE:
+ return 1;
+ case gl.SHORT:
+ case gl.UNSIGNED_SHORT:
+ case gl.UNSIGNED_SHORT_5_6_5:
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ return 2;
+ case gl.INT:
+ case gl.UNSIGNED_INT:
+ return 4;
+ default:
+ throw 'unknown gl type ' + glEnumToString(gl, type);
+ }
+};
+
+/**
+ * Returns the number of typed array elements per pixel for a given WebGL
+ * format/type combination. The corresponding typed array type can be determined
+ * by calling glTypeToTypedArrayType.
+ * @param {!WebGLRenderingContext} gl A WebGLRenderingContext.
+ * @param {GLenum} format The WebGL format (eg, gl.RGBA)
+ * @param {GLenum} type The WebGL type (eg, gl.UNSIGNED_BYTE)
+ * @return {number} The number of typed array elements per pixel.
+ */
+var getTypedArrayElementsPerPixel = function(gl, format, type) {
+ switch (type) {
+ case gl.UNSIGNED_SHORT_5_6_5:
+ case gl.UNSIGNED_SHORT_4_4_4_4:
+ case gl.UNSIGNED_SHORT_5_5_5_1:
+ return 1;
+ case gl.UNSIGNED_BYTE:
+ break;
+ default:
+ throw 'not a gl type for color information ' + glEnumToString(gl, type);
+ }
+
+ switch (format) {
+ case gl.RGBA:
+ return 4;
+ case gl.RGB:
+ return 3;
+ case gl.LUMINANCE_ALPHA:
+ return 2;
+ case gl.LUMINANCE:
+ case gl.ALPHA:
+ return 1;
+ default:
+ throw 'unknown gl format ' + glEnumToString(gl, format);
+ }
+};
+
+/**
+ * Fills the given texture with a solid color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!WebGLTexture} tex The texture to fill.
+ * @param {number} width The width of the texture to create.
+ * @param {number} height The height of the texture to create.
+ * @param {!Array.<number>} color The color to fill with.
+ * where each element is in the range 0 to 255.
+ * @param {number} opt_level The level of the texture to fill. Default = 0.
+ * @param {number} opt_format The format for the texture.
+ * @param {number} opt_internalFormat The internal format for the texture.
+ */
+var fillTexture = function(gl, tex, width, height, color, opt_level, opt_format, opt_type, opt_internalFormat) {
+ opt_level = opt_level || 0;
+ opt_format = opt_format || gl.RGBA;
+ opt_type = opt_type || gl.UNSIGNED_BYTE;
+ opt_internalFormat = opt_internalFormat || opt_format;
+ var pack = gl.getParameter(gl.UNPACK_ALIGNMENT);
+ var numComponents = color.length;
+ var bytesPerComponent = getBytesPerComponent(gl, opt_type);
+ var rowSize = numComponents * width * bytesPerComponent;
+ var paddedRowSize = Math.floor((rowSize + pack - 1) / pack) * pack;
+ var size = rowSize + (height - 1) * paddedRowSize;
+ size = Math.floor((size + bytesPerComponent - 1) / bytesPerComponent) * bytesPerComponent;
+ var buf = new (glTypeToTypedArrayType(gl, opt_type))(size);
+ for (var yy = 0; yy < height; ++yy) {
+ var off = yy * paddedRowSize;
+ for (var xx = 0; xx < width; ++xx) {
+ for (var jj = 0; jj < numComponents; ++jj) {
+ buf[off++] = color[jj];
+ }
+ }
+ }
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(
+ gl.TEXTURE_2D, opt_level, opt_internalFormat, width, height, 0,
+ opt_format, opt_type, buf);
+};
+
+/**
+ * Creates a texture and fills it with a solid color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} width The width of the texture to create.
+ * @param {number} height The height of the texture to create.
+ * @param {!Array.<number>} color The color to fill with. A 4 element array
+ * where each element is in the range 0 to 255.
+ * @return {!WebGLTexture}
+ */
+var createColoredTexture = function(gl, width, height, color) {
+ var tex = gl.createTexture();
+ fillTexture(gl, tex, width, height, color);
+ return tex;
+};
+
+var ubyteToFloat = function(c) {
+ return c / 255;
+};
+
+var ubyteColorToFloatColor = function(color) {
+ var floatColor = [];
+ for (var ii = 0; ii < color.length; ++ii) {
+ floatColor[ii] = ubyteToFloat(color[ii]);
+ }
+ return floatColor;
+};
+
+/**
+ * Sets the "u_color" uniform of the current program to color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} color 4 element array of 0-1 color
+ * components.
+ */
+var setFloatDrawColor = function(gl, color) {
+ var program = gl.getParameter(gl.CURRENT_PROGRAM);
+ var colorLocation = gl.getUniformLocation(program, "u_color");
+ gl.uniform4fv(colorLocation, color);
+};
+
+/**
+ * Sets the "u_color" uniform of the current program to color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} color 4 element array of 0-255 color
+ * components.
+ */
+var setUByteDrawColor = function(gl, color) {
+ setFloatDrawColor(gl, ubyteColorToFloatColor(color));
+};
+
+/**
+ * Draws a previously setup quad in the given color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} color The color to draw with. A 4
+ * element array where each element is in the range 0 to
+ * 1.
+ */
+var drawFloatColorQuad = function(gl, color) {
+ var program = gl.getParameter(gl.CURRENT_PROGRAM);
+ var colorLocation = gl.getUniformLocation(program, "u_color");
+ gl.uniform4fv(colorLocation, color);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+};
+
+
+/**
+ * Draws a previously setup quad in the given color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} color The color to draw with. A 4
+ * element array where each element is in the range 0 to
+ * 255.
+ */
+var drawUByteColorQuad = function(gl, color) {
+ drawFloatColorQuad(gl, ubyteColorToFloatColor(color));
+};
+
+/**
+ * Draws a previously setupUnitQuad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ */
+var drawUnitQuad = function(gl) {
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+};
+
+/**
+ * Clears then Draws a previously setupUnitQuad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} opt_color The color to fill clear with before
+ * drawing. A 4 element array where each element is in the range 0 to
+ * 255. Default [255, 255, 255, 255]
+ */
+var clearAndDrawUnitQuad = function(gl, opt_color) {
+ opt_color = opt_color || [255, 255, 255, 255];
+ gl.clearColor(
+ opt_color[0] / 255,
+ opt_color[1] / 255,
+ opt_color[2] / 255,
+ opt_color[3] / 255);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ drawUnitQuad(gl);
+};
+
+/**
+ * Draws a quad previously setup with setupIndexedQuad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} gridRes Resolution of grid.
+ */
+var drawIndexedQuad = function(gl, gridRes) {
+ gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
+};
+
+/**
+ * Draws a previously setupIndexedQuad
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} gridRes Resolution of grid.
+ * @param {!Array.<number>} opt_color The color to fill clear with before
+ * drawing. A 4 element array where each element is in the range 0 to
+ * 255. Default [255, 255, 255, 255]
+ */
+var clearAndDrawIndexedQuad = function(gl, gridRes, opt_color) {
+ opt_color = opt_color || [255, 255, 255, 255];
+ gl.clearColor(
+ opt_color[0] / 255,
+ opt_color[1] / 255,
+ opt_color[2] / 255,
+ opt_color[3] / 255);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ drawIndexedQuad(gl, gridRes);
+};
+
+/**
+ * Clips a range to min, max
+ * (Eg. clipToRange(-5,7,0,20) would return {value:0,extent:2}
+ * @param {number} value start of range
+ * @param {number} extent extent of range
+ * @param {number} min min.
+ * @param {number} max max.
+ * @return {!{value:number,extent:number}} The clipped value.
+ */
+var clipToRange = function(value, extent, min, max) {
+ if (value < min) {
+ extent -= min - value;
+ value = min;
+ }
+ var end = value + extent;
+ if (end > max) {
+ extent -= end - max;
+ }
+ if (extent < 0) {
+ value = max;
+ extent = 0;
+ }
+ return {value:value, extent: extent};
+};
+
+/**
+ * Determines if the passed context is an instance of a WebGLRenderingContext
+ * or later variant (like WebGL2RenderingContext)
+ * @param {CanvasRenderingContext} ctx The context to check.
+ */
+var isWebGLContext = function(ctx) {
+ if (ctx instanceof WebGLRenderingContext)
+ return true;
+
+ if ('WebGL2RenderingContext' in window && ctx instanceof WebGL2RenderingContext)
+ return true;
+
+ return false;
+};
+
+/**
+ * Creates a check rect is used by checkCanvasRects.
+ * @param {number} x left corner of region to check.
+ * @param {number} y bottom corner of region to check in case of checking from
+ * a GL context or top corner in case of checking from a 2D context.
+ * @param {number} width width of region to check.
+ * @param {number} height width of region to check.
+ * @param {!Array.<number>} color The color expected. A 4 element array where
+ * each element is in the range 0 to 255.
+ * @param {string} opt_msg Message to associate with success. Eg
+ * ("should be red").
+ * @param {number} opt_errorRange Optional. Acceptable error in
+ * color checking. 0 by default.
+ */
+var makeCheckRect = function(x, y, width, height, color, msg, errorRange) {
+ var rect = {
+ 'x': x, 'y': y,
+ 'width': width, 'height': height,
+ 'color': color, 'msg': msg,
+ 'errorRange': errorRange,
+
+ 'checkRect': function (buf, l, b, w) {
+ for (var px = (x - l) ; px < (x + width - l) ; ++px) {
+ for (var py = (y - b) ; py < (y + height - b) ; ++py) {
+ var offset = (py * w + px) * 4;
+ for (var j = 0; j < color.length; ++j) {
+ if (Math.abs(buf[offset + j] - color[j]) > errorRange) {
+ testFailed(msg);
+ var was = buf[offset + 0].toString();
+ for (j = 1; j < color.length; ++j) {
+ was += "," + buf[offset + j];
+ }
+ debug('at (' + px + ', ' + py +
+ ') expected: ' + color + ' was ' + was);
+ return;
+ }
+ }
+ }
+ }
+ testPassed(msg);
+ }
+ }
+ return rect;
+};
+
+/**
+ * Checks that a portions of a canvas or the currently attached framebuffer is 1 color.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ * WebGLRenderingContext or 2D context to use.
+ * @param {!Array.<checkRect>} array of rects to check for matching color.
+ */
+var checkCanvasRects = function(gl, rects) {
+ if (rects.length > 0) {
+ var left = rects[0].x;
+ var right = rects[0].x + rects[1].width;
+ var bottom = rects[0].y;
+ var top = rects[0].y + rects[0].height;
+ for (var i = 1; i < rects.length; ++i) {
+ left = Math.min(left, rects[i].x);
+ right = Math.max(right, rects[i].x + rects[i].width);
+ bottom = Math.min(bottom, rects[i].y);
+ top = Math.max(top, rects[i].y + rects[i].height);
+ }
+ var width = right - left;
+ var height = top - bottom;
+ var buf = new Uint8Array(width * height * 4);
+ gl.readPixels(left, bottom, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ for (var i = 0; i < rects.length; ++i) {
+ rects[i].checkRect(buf, left, bottom, width);
+ }
+ }
+};
+
+/**
+ * Checks that a portion of a canvas or the currently attached framebuffer is 1 color.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ * WebGLRenderingContext or 2D context to use.
+ * @param {number} x left corner of region to check.
+ * @param {number} y bottom corner of region to check in case of checking from
+ * a GL context or top corner in case of checking from a 2D context.
+ * @param {number} width width of region to check.
+ * @param {number} height width of region to check.
+ * @param {!Array.<number>} color The color expected. A 4 element array where
+ * each element is in the range 0 to 255.
+ * @param {number} opt_errorRange Optional. Acceptable error in
+ * color checking. 0 by default.
+ * @param {!function()} sameFn Function to call if all pixels
+ * are the same as color.
+ * @param {!function()} differentFn Function to call if a pixel
+ * is different than color
+ * @param {!function()} logFn Function to call for logging.
+ * @param {Uint8Array} opt_readBackBuf typically passed to reuse existing
+ * buffer while reading back pixels.
+ */
+var checkCanvasRectColor = function(gl, x, y, width, height, color, opt_errorRange, sameFn, differentFn, logFn, opt_readBackBuf) {
+ if (isWebGLContext(gl) && !gl.getParameter(gl.FRAMEBUFFER_BINDING)) {
+ // We're reading the backbuffer so clip.
+ var xr = clipToRange(x, width, 0, gl.canvas.width);
+ var yr = clipToRange(y, height, 0, gl.canvas.height);
+ if (!xr.extent || !yr.extent) {
+ logFn("checking rect: effective width or height is zero");
+ sameFn();
+ return;
+ }
+ x = xr.value;
+ y = yr.value;
+ width = xr.extent;
+ height = yr.extent;
+ }
+ var errorRange = opt_errorRange || 0;
+ if (!errorRange.length) {
+ errorRange = [errorRange, errorRange, errorRange, errorRange]
+ }
+ var buf;
+ if (isWebGLContext(gl)) {
+ buf = opt_readBackBuf ? opt_readBackBuf : new Uint8Array(width * height * 4);
+ gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ } else {
+ buf = gl.getImageData(x, y, width, height).data;
+ }
+ for (var i = 0; i < width * height; ++i) {
+ var offset = i * 4;
+ for (var j = 0; j < color.length; ++j) {
+ if (Math.abs(buf[offset + j] - color[j]) > errorRange[j]) {
+ var was = buf[offset + 0].toString();
+ for (j = 1; j < color.length; ++j) {
+ was += "," + buf[offset + j];
+ }
+ differentFn('at (' + (x + (i % width)) + ', ' + (y + Math.floor(i / width)) +
+ ') expected: ' + color + ' was ' + was);
+ return;
+ }
+ }
+ }
+ sameFn();
+};
+
+/**
+ * Checks that a portion of a canvas or the currently attached framebuffer is 1 color.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ * WebGLRenderingContext or 2D context to use.
+ * @param {number} x left corner of region to check.
+ * @param {number} y bottom corner of region to check in case of checking from
+ * a GL context or top corner in case of checking from a 2D context.
+ * @param {number} width width of region to check.
+ * @param {number} height width of region to check.
+ * @param {!Array.<number>} color The color expected. A 4 element array where
+ * each element is in the range 0 to 255.
+ * @param {string} opt_msg Message to associate with success or failure. Eg
+ * ("should be red").
+ * @param {number} opt_errorRange Optional. Acceptable error in
+ * color checking. 0 by default.
+ */
+var checkCanvasRect = function(gl, x, y, width, height, color, opt_msg, opt_errorRange) {
+ checkCanvasRectColor(
+ gl, x, y, width, height, color, opt_errorRange,
+ function() {
+ var msg = opt_msg;
+ if (msg === undefined)
+ msg = "should be " + color.toString();
+ testPassed(msg);
+ },
+ function(differentMsg) {
+ var msg = opt_msg;
+ if (msg === undefined)
+ msg = "should be " + color.toString();
+ testFailed(msg + "\n" + differentMsg);
+ },
+ debug);
+};
+
+/**
+ * Checks that an entire canvas or the currently attached framebuffer is 1 color.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ * WebGLRenderingContext or 2D context to use.
+ * @param {!Array.<number>} color The color expected. A 4 element array where
+ * each element is in the range 0 to 255.
+ * @param {string} msg Message to associate with success. Eg ("should be red").
+ * @param {number} errorRange Optional. Acceptable error in
+ * color checking. 0 by default.
+ */
+var checkCanvas = function(gl, color, msg, errorRange) {
+ checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, color, msg, errorRange);
+};
+
+/**
+ * Checks a rectangular area both inside the area and outside
+ * the area.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ * WebGLRenderingContext or 2D context to use.
+ * @param {number} x left corner of region to check.
+ * @param {number} y bottom corner of region to check in case of checking from
+ * a GL context or top corner in case of checking from a 2D context.
+ * @param {number} width width of region to check.
+ * @param {number} height width of region to check.
+ * @param {!Array.<number>} innerColor The color expected inside
+ * the area. A 4 element array where each element is in the
+ * range 0 to 255.
+ * @param {!Array.<number>} outerColor The color expected
+ * outside. A 4 element array where each element is in the
+ * range 0 to 255.
+ * @param {!number} opt_edgeSize: The number of pixels to skip
+ * around the edges of the area. Defaut 0.
+ * @param {!{width:number, height:number}} opt_outerDimensions
+ * The outer dimensions. Default the size of gl.canvas.
+ */
+var checkAreaInAndOut = function(gl, x, y, width, height, innerColor, outerColor, opt_edgeSize, opt_outerDimensions) {
+ var outerDimensions = opt_outerDimensions || { width: gl.canvas.width, height: gl.canvas.height };
+ var edgeSize = opt_edgeSize || 0;
+ checkCanvasRect(gl, x + edgeSize, y + edgeSize, width - edgeSize * 2, height - edgeSize * 2, innerColor);
+ checkCanvasRect(gl, 0, 0, x - edgeSize, outerDimensions.height, outerColor);
+ checkCanvasRect(gl, x + width + edgeSize, 0, outerDimensions.width - x - width - edgeSize, outerDimensions.height, outerColor);
+ checkCanvasRect(gl, 0, 0, outerDimensions.width, y - edgeSize, outerColor);
+ checkCanvasRect(gl, 0, y + height + edgeSize, outerDimensions.width, outerDimensions.height - y - height - edgeSize, outerColor);
+};
+
+/**
+ * Checks that an entire buffer matches the floating point values provided.
+ * (WebGL 2.0 only)
+ * @param {!WebGL2RenderingContext} gl The WebGL2RenderingContext to use.
+ * @param {number} target The buffer target to bind to.
+ * @param {!Array.<number>} expected The values expected.
+ * @param {string} opt_msg Optional. Message to associate with success. Eg ("should be red").
+ * @param {number} opt_errorRange Optional. Acceptable error in value checking. 0.001 by default.
+ */
+var checkFloatBuffer = function(gl, target, expected, opt_msg, opt_errorRange) {
+ if (opt_msg === undefined)
+ opt_msg = "buffer should match expected values";
+
+ if (opt_errorRange === undefined)
+ opt_errorRange = 0.001;
+
+ var floatArray = new Float32Array(expected.length);
+ gl.getBufferSubData(target, 0, floatArray);
+
+ for (var i = 0; i < expected.length; i++) {
+ if (Math.abs(floatArray[i] - expected[i]) > opt_errorRange) {
+ testFailed(opt_msg);
+ debug('at [' + i + '] expected: ' + expected[i] + ' was ' + floatArray[i]);
+ return;
+ }
+ }
+ testPassed(opt_msg);
+};
+
+/**
+ * Loads a texture, calls callback when finished.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} url URL of image to load
+ * @param {function(!Image): void} callback Function that gets called after
+ * image has loaded
+ * @return {!WebGLTexture} The created texture.
+ */
+var loadTexture = function(gl, url, callback) {
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ var image = new Image();
+ image.onload = function() {
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
+ callback(image);
+ };
+ image.src = url;
+ return texture;
+};
+
+/**
+ * Checks whether the bound texture has expected dimensions. One corner pixel
+ * of the texture will be changed as a side effect.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!WebGLTexture} texture The texture to check.
+ * @param {number} width Expected width.
+ * @param {number} height Expected height.
+ * @param {GLenum} opt_format The texture's format. Defaults to RGBA.
+ * @param {GLenum} opt_type The texture's type. Defaults to UNSIGNED_BYTE.
+ */
+var checkTextureSize = function(gl, width, height, opt_format, opt_type) {
+ opt_format = opt_format || gl.RGBA;
+ opt_type = opt_type || gl.UNSIGNED_BYTE;
+
+ var numElements = getTypedArrayElementsPerPixel(gl, opt_format, opt_type);
+ var buf = new (glTypeToTypedArrayType(gl, opt_type))(numElements);
+
+ var errors = 0;
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, width - 1, height - 1, 1, 1, opt_format, opt_type, buf);
+ if (gl.getError() != gl.NO_ERROR) {
+ testFailed("Texture was smaller than the expected size " + width + "x" + height);
+ ++errors;
+ }
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, width - 1, height, 1, 1, opt_format, opt_type, buf);
+ if (gl.getError() == gl.NO_ERROR) {
+ testFailed("Texture was taller than " + height);
+ ++errors;
+ }
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, width, height - 1, 1, 1, opt_format, opt_type, buf);
+ if (gl.getError() == gl.NO_ERROR) {
+ testFailed("Texture was wider than " + width);
+ ++errors;
+ }
+ if (errors == 0) {
+ testPassed("Texture had the expected size " + width + "x" + height);
+ }
+};
+
+/**
+ * Makes a shallow copy of an object.
+ * @param {!Object} src Object to copy
+ * @return {!Object} The copy of src.
+ */
+var shallowCopyObject = function(src) {
+ var dst = {};
+ for (var attr in src) {
+ if (src.hasOwnProperty(attr)) {
+ dst[attr] = src[attr];
+ }
+ }
+ return dst;
+};
+
+/**
+ * Checks if an attribute exists on an object case insensitive.
+ * @param {!Object} obj Object to check
+ * @param {string} attr Name of attribute to look for.
+ * @return {string?} The name of the attribute if it exists,
+ * undefined if not.
+ */
+var hasAttributeCaseInsensitive = function(obj, attr) {
+ var lower = attr.toLowerCase();
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key) && key.toLowerCase() == lower) {
+ return key;
+ }
+ }
+};
+
+/**
+ * Returns a map of URL querystring options
+ * @return {Object?} Object containing all the values in the URL querystring
+ */
+var getUrlOptions = (function() {
+ var _urlOptionsParsed = false;
+ var _urlOptions = {};
+ return function() {
+ if (!_urlOptionsParsed) {
+ var s = window.location.href;
+ var q = s.indexOf("?");
+ var e = s.indexOf("#");
+ if (e < 0) {
+ e = s.length;
+ }
+ var query = s.substring(q + 1, e);
+ var pairs = query.split("&");
+ for (var ii = 0; ii < pairs.length; ++ii) {
+ var keyValue = pairs[ii].split("=");
+ var key = keyValue[0];
+ var value = decodeURIComponent(keyValue[1]);
+ _urlOptions[key] = value;
+ }
+ _urlOptionsParsed = true;
+ }
+
+ return _urlOptions;
+ }
+})();
+
+var default3DContextVersion = 1;
+
+/**
+ * Set the default context version for create3DContext.
+ * Initially the default version is 1.
+ * @param {number} Default version of WebGL contexts.
+ */
+var setDefault3DContextVersion = function(version) {
+ default3DContextVersion = version;
+};
+
+/**
+ * Get the default contex version for create3DContext.
+ * First it looks at the URI option |webglVersion|. If it does not exist,
+ * then look at the global default3DContextVersion variable.
+ */
+var getDefault3DContextVersion = function() {
+ return parseInt(getUrlOptions().webglVersion, 10) || default3DContextVersion;
+};
+
+/**
+ * Creates a webgl context.
+ * @param {!Canvas|string} opt_canvas The canvas tag to get
+ * context from. If one is not passed in one will be
+ * created. If it's a string it's assumed to be the id of a
+ * canvas.
+ * @param {Object} opt_attributes Context attributes.
+ * @param {!number} opt_version Version of WebGL context to create.
+ * The default version can be set by calling setDefault3DContextVersion.
+ * @return {!WebGLRenderingContext} The created context.
+ */
+var create3DContext = function(opt_canvas, opt_attributes, opt_version) {
+ if (window.initTestingHarness) {
+ window.initTestingHarness();
+ }
+ var attributes = shallowCopyObject(opt_attributes || {});
+ if (!hasAttributeCaseInsensitive(attributes, "antialias")) {
+ attributes.antialias = false;
+ }
+ if (!opt_version) {
+ opt_version = parseInt(getUrlOptions().webglVersion, 10) || default3DContextVersion;
+ }
+ opt_canvas = opt_canvas || document.createElement("canvas");
+ if (typeof opt_canvas == 'string') {
+ opt_canvas = document.getElementById(opt_canvas);
+ }
+ var context = null;
+
+ var names;
+ switch (opt_version) {
+ case 2:
+ names = ["webgl2", "experimental-webgl2"]; break;
+ default:
+ names = ["webgl", "experimental-webgl"]; break;
+ }
+
+ for (var i = 0; i < names.length; ++i) {
+ try {
+ context = opt_canvas.getContext(names[i], attributes);
+ } catch (e) {
+ }
+ if (context) {
+ break;
+ }
+ }
+ if (!context) {
+ testFailed("Unable to fetch WebGL rendering context for Canvas");
+ }
+ return context;
+};
+
+/**
+ * Defines the exception type for a GL error.
+ * @constructor
+ * @param {string} message The error message.
+ * @param {number} error GL error code
+ */
+function GLErrorException (message, error) {
+ this.message = message;
+ this.name = "GLErrorException";
+ this.error = error;
+};
+
+/**
+ * Wraps a WebGL function with a function that throws an exception if there is
+ * an error.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} fname Name of function to wrap.
+ * @return {function()} The wrapped function.
+ */
+var createGLErrorWrapper = function(context, fname) {
+ return function() {
+ var rv = context[fname].apply(context, arguments);
+ var err = context.getError();
+ if (err != context.NO_ERROR) {
+ var msg = "GL error " + glEnumToString(context, err) + " in " + fname;
+ throw new GLErrorException(msg, err);
+ }
+ return rv;
+ };
+};
+
+/**
+ * Creates a WebGL context where all functions are wrapped to throw an exception
+ * if there is an error.
+ * @param {!Canvas} canvas The HTML canvas to get a context from.
+ * @param {Object} opt_attributes Context attributes.
+ * @param {!number} opt_version Version of WebGL context to create
+ * @return {!Object} The wrapped context.
+ */
+function create3DContextWithWrapperThatThrowsOnGLError(canvas, opt_attributes, opt_version) {
+ var context = create3DContext(canvas, opt_attributes, opt_version);
+ var wrap = {};
+ for (var i in context) {
+ try {
+ if (typeof context[i] == 'function') {
+ wrap[i] = createGLErrorWrapper(context, i);
+ } else {
+ wrap[i] = context[i];
+ }
+ } catch (e) {
+ error("createContextWrapperThatThrowsOnGLError: Error accessing " + i);
+ }
+ }
+ wrap.getError = function() {
+ return context.getError();
+ };
+ return wrap;
+};
+
+/**
+ * Tests that an evaluated expression generates a specific GL error.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number|Array.<number>} glErrors The expected gl error or an array of expected errors.
+ * @param {string} evalStr The string to evaluate.
+ */
+var shouldGenerateGLError = function(gl, glErrors, evalStr, opt_msg) {
+ var exception;
+ try {
+ eval(evalStr);
+ } catch (e) {
+ exception = e;
+ }
+ if (exception) {
+ testFailed(evalStr + " threw exception " + exception);
+ } else {
+ if (!opt_msg) {
+ opt_msg = "after evaluating: " + evalStr;
+ }
+ glErrorShouldBe(gl, glErrors, opt_msg);
+ }
+};
+
+/**
+ * Tests that an evaluated expression does not generate a GL error.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} evalStr The string to evaluate.
+ */
+var failIfGLError = function(gl, evalStr) {
+ var exception;
+ try {
+ eval(evalStr);
+ } catch (e) {
+ exception = e;
+ }
+ if (exception) {
+ testFailed(evalStr + " threw exception " + exception);
+ } else {
+ glErrorShouldBeImpl(gl, gl.NO_ERROR, false, "after evaluating: " + evalStr);
+ }
+};
+
+/**
+ * Tests that the first error GL returns is the specified error.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number|Array.<number>} glErrors The expected gl error or an array of expected errors.
+ * @param {string} opt_msg Optional additional message.
+ */
+var glErrorShouldBe = function(gl, glErrors, opt_msg) {
+ glErrorShouldBeImpl(gl, glErrors, true, opt_msg);
+};
+
+
+
+/**
+ * Tests that the first error GL returns is the specified error. Allows suppression of successes.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number|Array.<number>} glErrors The expected gl error or an array of expected errors.
+ * @param {boolean} reportSuccesses Whether to report successes as passes, or to silently pass.
+ * @param {string} opt_msg Optional additional message.
+ */
+var glErrorShouldBeImpl = function(gl, glErrors, reportSuccesses, opt_msg) {
+ if (!glErrors.length) {
+ glErrors = [glErrors];
+ }
+ opt_msg = opt_msg || "";
+ var err = gl.getError();
+ var ndx = glErrors.indexOf(err);
+ var errStrs = [];
+ for (var ii = 0; ii < glErrors.length; ++ii) {
+ errStrs.push(glEnumToString(gl, glErrors[ii]));
+ }
+ var expected = errStrs.join(" or ");
+ if (ndx < 0) {
+ var msg = "getError expected" + ((glErrors.length > 1) ? " one of: " : ": ");
+ testFailed(msg + expected + ". Was " + glEnumToString(gl, err) + " : " + opt_msg);
+ } else if (reportSuccesses) {
+ var msg = "getError was " + ((glErrors.length > 1) ? "one of: " : "expected value: ");
+ testPassed(msg + expected + " : " + opt_msg);
+ }
+};
+
+/**
+ * Links a WebGL program, throws if there are errors.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!WebGLProgram} program The WebGLProgram to link.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ */
+var linkProgram = function(gl, program, opt_errorCallback) {
+ var errFn = opt_errorCallback || testFailed;
+ // Link the program
+ gl.linkProgram(program);
+
+ // Check the link status
+ var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+ if (!linked) {
+ // something went wrong with the link
+ var error = gl.getProgramInfoLog (program);
+
+ errFn("Error in program linking:" + error);
+
+ gl.deleteProgram(program);
+ }
+};
+
+/**
+ * Loads text from an external file. This function is asynchronous.
+ * @param {string} url The url of the external file.
+ * @param {!function(bool, string): void} callback that is sent a bool for
+ * success and the string.
+ */
+var loadTextFileAsync = function(url, callback) {
+ log ("loading: " + url);
+ var error = 'loadTextFileAsync failed to load url "' + url + '"';
+ var request;
+ if (window.XMLHttpRequest) {
+ request = new XMLHttpRequest();
+ if (request.overrideMimeType) {
+ request.overrideMimeType('text/plain');
+ }
+ } else {
+ throw 'XMLHttpRequest is disabled';
+ }
+ try {
+ request.open('GET', url, true);
+ request.onreadystatechange = function() {
+ if (request.readyState == 4) {
+ var text = '';
+ // HTTP reports success with a 200 status. The file protocol reports
+ // success with zero. HTTP does not use zero as a status code (they
+ // start at 100).
+ // https://developer.mozilla.org/En/Using_XMLHttpRequest
+ var success = request.status == 200 || request.status == 0;
+ if (success) {
+ text = request.responseText;
+ log("completed load request: " + url);
+ } else {
+ log("loading " + url + " resulted in unexpected status: " + request.status + " " + request.statusText);
+ }
+ callback(success, text);
+ }
+ };
+ request.onerror = function(errorEvent) {
+ log("error occurred loading " + url);
+ callback(false, '');
+ };
+ request.send(null);
+ } catch (err) {
+ log("failed to load: " + url + " with exception " + err.message);
+ callback(false, '');
+ }
+};
+
+/**
+ * Recursively loads a file as a list. Each line is parsed for a relative
+ * path. If the file ends in .txt the contents of that file is inserted in
+ * the list.
+ *
+ * @param {string} url The url of the external file.
+ * @param {!function(bool, Array<string>): void} callback that is sent a bool
+ * for success and the array of strings.
+ */
+var getFileListAsync = function(url, callback) {
+ var files = [];
+
+ var getFileListImpl = function(url, callback) {
+ var files = [];
+ if (url.substr(url.length - 4) == '.txt') {
+ loadTextFileAsync(url, function() {
+ return function(success, text) {
+ if (!success) {
+ callback(false, '');
+ return;
+ }
+ var lines = text.split('\n');
+ var prefix = '';
+ var lastSlash = url.lastIndexOf('/');
+ if (lastSlash >= 0) {
+ prefix = url.substr(0, lastSlash + 1);
+ }
+ var fail = false;
+ var count = 1;
+ var index = 0;
+ for (var ii = 0; ii < lines.length; ++ii) {
+ var str = lines[ii].replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+ if (str.length > 4 &&
+ str[0] != '#' &&
+ str[0] != ";" &&
+ str.substr(0, 2) != "//") {
+ var names = str.split(/ +/);
+ var new_url = prefix + str;
+ if (names.length == 1) {
+ new_url = prefix + str;
+ ++count;
+ getFileListImpl(new_url, function(index) {
+ return function(success, new_files) {
+ log("got files: " + new_files.length);
+ if (success) {
+ files[index] = new_files;
+ }
+ finish(success);
+ };
+ }(index++));
+ } else {
+ var s = "";
+ var p = "";
+ for (var jj = 0; jj < names.length; ++jj) {
+ s += p + prefix + names[jj];
+ p = " ";
+ }
+ files[index++] = s;
+ }
+ }
+ }
+ finish(true);
+
+ function finish(success) {
+ if (!success) {
+ fail = true;
+ }
+ --count;
+ log("count: " + count);
+ if (!count) {
+ callback(!fail, files);
+ }
+ }
+ }
+ }());
+
+ } else {
+ files.push(url);
+ callback(true, files);
+ }
+ };
+
+ getFileListImpl(url, function(success, files) {
+ // flatten
+ var flat = [];
+ flatten(files);
+ function flatten(files) {
+ for (var ii = 0; ii < files.length; ++ii) {
+ var value = files[ii];
+ if (typeof(value) == "string") {
+ flat.push(value);
+ } else {
+ flatten(value);
+ }
+ }
+ }
+ callback(success, flat);
+ });
+};
+
+/**
+ * Gets a file from a file/URL.
+ * @param {string} file the URL of the file to get.
+ * @return {string} The contents of the file.
+ */
+var readFile = function(file) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", file, false);
+ xhr.send();
+ return xhr.responseText.replace(/\r/g, "");
+};
+
+var readFileList = function(url) {
+ var files = [];
+ if (url.substr(url.length - 4) == '.txt') {
+ var lines = readFile(url).split('\n');
+ var prefix = '';
+ var lastSlash = url.lastIndexOf('/');
+ if (lastSlash >= 0) {
+ prefix = url.substr(0, lastSlash + 1);
+ }
+ for (var ii = 0; ii < lines.length; ++ii) {
+ var str = lines[ii].replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+ if (str.length > 4 &&
+ str[0] != '#' &&
+ str[0] != ";" &&
+ str.substr(0, 2) != "//") {
+ var names = str.split(/ +/);
+ if (names.length == 1) {
+ var new_url = prefix + str;
+ files = files.concat(readFileList(new_url));
+ } else {
+ var s = "";
+ var p = "";
+ for (var jj = 0; jj < names.length; ++jj) {
+ s += p + prefix + names[jj];
+ p = " ";
+ }
+ files.push(s);
+ }
+ }
+ }
+ } else {
+ files.push(url);
+ }
+ return files;
+};
+
+/**
+ * Loads a shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} shaderSource The shader source.
+ * @param {number} shaderType The type of shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ * @param {string} opt_shaderLabel Label that identifies the shader source in
+ * the log.
+ * @param {string} opt_url URL from where the shader source was loaded from.
+ * If opt_logShaders is set, then a link to the source file will also be
+ * added.
+ * @param {boolean} Skip compilation status check. Default = false.
+ * @return {!WebGLShader} The created shader.
+ */
+var loadShader = function(
+ gl, shaderSource, shaderType, opt_errorCallback, opt_logShaders,
+ opt_shaderLabel, opt_url, opt_skipCompileStatus) {
+ var errFn = opt_errorCallback || error;
+ // Create the shader object
+ var shader = gl.createShader(shaderType);
+ if (shader == null) {
+ errFn("*** Error: unable to create shader '"+shaderSource+"'");
+ return null;
+ }
+
+ // Load the shader source
+ gl.shaderSource(shader, shaderSource);
+ var err = gl.getError();
+ if (err != gl.NO_ERROR) {
+ errFn("*** Error loading shader '" + shader + "':" + glEnumToString(gl, err));
+ return null;
+ }
+
+ // Compile the shader
+ gl.compileShader(shader);
+
+ if (opt_logShaders) {
+ var label = shaderType == gl.VERTEX_SHADER ? 'vertex shader' : 'fragment_shader';
+ if (opt_shaderLabel) {
+ label = opt_shaderLabel + ' ' + label;
+ }
+ addShaderSources(
+ gl, document.getElementById('console'), label, shader, shaderSource, opt_url);
+ }
+
+ // Check the compile status
+ if (!opt_skipCompileStatus) {
+ var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
+ if (!compiled) {
+ // Something went wrong during compilation; get the error
+ lastError = gl.getShaderInfoLog(shader);
+ errFn("*** Error compiling " + glEnumToString(gl, shaderType) + " '" + shader + "':" + lastError);
+ gl.deleteShader(shader);
+ return null;
+ }
+ }
+
+ return shader;
+}
+
+/**
+ * Loads a shader from a URL.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {file} file The URL of the shader source.
+ * @param {number} type The type of shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ * @param {boolean} Skip compilation status check. Default = false.
+ * @return {!WebGLShader} The created shader.
+ */
+var loadShaderFromFile = function(
+ gl, file, type, opt_errorCallback, opt_logShaders, opt_skipCompileStatus) {
+ var shaderSource = readFile(file);
+ return loadShader(gl, shaderSource, type, opt_errorCallback,
+ opt_logShaders, undefined, file, opt_skipCompileStatus);
+};
+
+var loadShaderFromFileAsync = function(
+ gl, file, type, opt_errorCallback, opt_logShaders, opt_skipCompileStatus, callback) {
+ loadTextFileAsync(file, function(gl, type, opt_errorCallback, opt_logShaders, file, opt_skipCompileStatus){
+ return function(success, shaderSource) {
+ if (success) {
+ var shader = loadShader(gl, shaderSource, type, opt_errorCallback,
+ opt_logShaders, undefined, file, opt_skipCompileStatus);
+ callback(true, shader);
+ } else {
+ callback(false, null);
+ }
+ }
+ }(gl, type, opt_errorCallback, opt_logShaders, file, opt_skipCompileStatus));
+};
+
+/**
+ * Gets the content of script.
+ * @param {string} scriptId The id of the script tag.
+ * @return {string} The content of the script.
+ */
+var getScript = function(scriptId) {
+ var shaderScript = document.getElementById(scriptId);
+ if (!shaderScript) {
+ throw("*** Error: unknown script element " + scriptId);
+ }
+ return shaderScript.text;
+};
+
+/**
+ * Loads a shader from a script tag.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} scriptId The id of the script tag.
+ * @param {number} opt_shaderType The type of shader. If not passed in it will
+ * be derived from the type of the script tag.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ * @param {boolean} Skip compilation status check. Default = false.
+ * @return {!WebGLShader} The created shader.
+ */
+var loadShaderFromScript = function(
+ gl, scriptId, opt_shaderType, opt_errorCallback, opt_logShaders, opt_skipCompileStatus) {
+ var shaderSource = "";
+ var shaderScript = document.getElementById(scriptId);
+ if (!shaderScript) {
+ throw("*** Error: unknown script element " + scriptId);
+ }
+ shaderSource = shaderScript.text;
+
+ if (!opt_shaderType) {
+ if (shaderScript.type == "x-shader/x-vertex") {
+ opt_shaderType = gl.VERTEX_SHADER;
+ } else if (shaderScript.type == "x-shader/x-fragment") {
+ opt_shaderType = gl.FRAGMENT_SHADER;
+ } else {
+ throw("*** Error: unknown shader type");
+ return null;
+ }
+ }
+
+ return loadShader(gl, shaderSource, opt_shaderType, opt_errorCallback,
+ opt_logShaders, undefined, undefined, opt_skipCompileStatus);
+};
+
+var loadStandardProgram = function(gl) {
+ var program = gl.createProgram();
+ gl.attachShader(program, loadStandardVertexShader(gl));
+ gl.attachShader(program, loadStandardFragmentShader(gl));
+ gl.bindAttribLocation(program, 0, "a_vertex");
+ gl.bindAttribLocation(program, 1, "a_normal");
+ linkProgram(gl, program);
+ return program;
+};
+
+var loadStandardProgramAsync = function(gl, callback) {
+ loadStandardVertexShaderAsync(gl, function(gl) {
+ return function(success, vs) {
+ if (success) {
+ loadStandardFragmentShaderAsync(gl, function(vs) {
+ return function(success, fs) {
+ if (success) {
+ var program = gl.createProgram();
+ gl.attachShader(program, vs);
+ gl.attachShader(program, fs);
+ gl.bindAttribLocation(program, 0, "a_vertex");
+ gl.bindAttribLocation(program, 1, "a_normal");
+ linkProgram(gl, program);
+ callback(true, program);
+ } else {
+ callback(false, null);
+ }
+ };
+ }(vs));
+ } else {
+ callback(false, null);
+ }
+ };
+ }(gl));
+};
+
+/**
+ * Loads shaders from files, creates a program, attaches the shaders and links.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} vertexShaderPath The URL of the vertex shader.
+ * @param {string} fragmentShaderPath The URL of the fragment shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @return {!WebGLProgram} The created program.
+ */
+var loadProgramFromFile = function(
+ gl, vertexShaderPath, fragmentShaderPath, opt_errorCallback) {
+ var program = gl.createProgram();
+ var vs = loadShaderFromFile(
+ gl, vertexShaderPath, gl.VERTEX_SHADER, opt_errorCallback);
+ var fs = loadShaderFromFile(
+ gl, fragmentShaderPath, gl.FRAGMENT_SHADER, opt_errorCallback);
+ if (vs && fs) {
+ gl.attachShader(program, vs);
+ gl.attachShader(program, fs);
+ linkProgram(gl, program, opt_errorCallback);
+ }
+ if (vs) {
+ gl.deleteShader(vs);
+ }
+ if (fs) {
+ gl.deleteShader(fs);
+ }
+ return program;
+};
+
+/**
+ * Loads shaders from script tags, creates a program, attaches the shaders and
+ * links.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} vertexScriptId The id of the script tag that contains the
+ * vertex shader.
+ * @param {string} fragmentScriptId The id of the script tag that contains the
+ * fragment shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @return {!WebGLProgram} The created program.
+ */
+var loadProgramFromScript = function loadProgramFromScript(
+ gl, vertexScriptId, fragmentScriptId, opt_errorCallback) {
+ var program = gl.createProgram();
+ gl.attachShader(
+ program,
+ loadShaderFromScript(
+ gl, vertexScriptId, gl.VERTEX_SHADER, opt_errorCallback));
+ gl.attachShader(
+ program,
+ loadShaderFromScript(
+ gl, fragmentScriptId, gl.FRAGMENT_SHADER, opt_errorCallback));
+ linkProgram(gl, program, opt_errorCallback);
+ return program;
+};
+
+/**
+ * Loads shaders from source, creates a program, attaches the shaders and
+ * links.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!WebGLShader} vertexShader The vertex shader.
+ * @param {!WebGLShader} fragmentShader The fragment shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @return {!WebGLProgram} The created program.
+ */
+var createProgram = function(gl, vertexShader, fragmentShader, opt_errorCallback) {
+ var program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ linkProgram(gl, program, opt_errorCallback);
+ return program;
+};
+
+/**
+ * Loads shaders from source, creates a program, attaches the shaders and
+ * links.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} vertexShader The vertex shader source.
+ * @param {string} fragmentShader The fragment shader source.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ * @return {!WebGLProgram} The created program.
+ */
+var loadProgram = function(
+ gl, vertexShader, fragmentShader, opt_errorCallback, opt_logShaders) {
+ var program;
+ var vs = loadShader(
+ gl, vertexShader, gl.VERTEX_SHADER, opt_errorCallback, opt_logShaders);
+ var fs = loadShader(
+ gl, fragmentShader, gl.FRAGMENT_SHADER, opt_errorCallback, opt_logShaders);
+ if (vs && fs) {
+ program = createProgram(gl, vs, fs, opt_errorCallback)
+ }
+ if (vs) {
+ gl.deleteShader(vs);
+ }
+ if (fs) {
+ gl.deleteShader(fs);
+ }
+ return program;
+};
+
+/**
+ * Loads shaders from source, creates a program, attaches the shaders and
+ * links but expects error.
+ *
+ * GLSL 1.0.17 10.27 effectively says that compileShader can
+ * always succeed as long as linkProgram fails so we can't
+ * rely on compileShader failing. This function expects
+ * one of the shader to fail OR linking to fail.
+ *
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} vertexShaderScriptId The vertex shader.
+ * @param {string} fragmentShaderScriptId The fragment shader.
+ * @return {WebGLProgram} The created program.
+ */
+var loadProgramFromScriptExpectError = function(
+ gl, vertexShaderScriptId, fragmentShaderScriptId) {
+ var vertexShader = loadShaderFromScript(gl, vertexShaderScriptId);
+ if (!vertexShader) {
+ return null;
+ }
+ var fragmentShader = loadShaderFromScript(gl, fragmentShaderScriptId);
+ if (!fragmentShader) {
+ return null;
+ }
+ var linkSuccess = true;
+ var program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ linkSuccess = true;
+ linkProgram(gl, program, function() {
+ linkSuccess = false;
+ });
+ return linkSuccess ? program : null;
+};
+
+
+var getActiveMap = function(gl, program, typeInfo) {
+ var numVariables = gl.getProgramParameter(program, gl[typeInfo.param]);
+ var variables = {};
+ for (var ii = 0; ii < numVariables; ++ii) {
+ var info = gl[typeInfo.activeFn](program, ii);
+ variables[info.name] = {
+ name: info.name,
+ size: info.size,
+ type: info.type,
+ location: gl[typeInfo.locFn](program, info.name)
+ };
+ }
+ return variables;
+};
+
+/**
+ * Returns a map of attrib names to info about those
+ * attribs.
+ *
+ * eg:
+ * { "attrib1Name":
+ * {
+ * name: "attrib1Name",
+ * size: 1,
+ * type: gl.FLOAT_MAT2,
+ * location: 0
+ * },
+ * "attrib2Name[0]":
+ * {
+ * name: "attrib2Name[0]",
+ * size: 4,
+ * type: gl.FLOAT,
+ * location: 1
+ * },
+ * }
+ *
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {WebGLProgram} The program to query for attribs.
+ * @return the map.
+ */
+var getAttribMap = function(gl, program) {
+ return getActiveMap(gl, program, {
+ param: "ACTIVE_ATTRIBUTES",
+ activeFn: "getActiveAttrib",
+ locFn: "getAttribLocation"
+ });
+};
+
+/**
+ * Returns a map of uniform names to info about those uniforms.
+ *
+ * eg:
+ * { "uniform1Name":
+ * {
+ * name: "uniform1Name",
+ * size: 1,
+ * type: gl.FLOAT_MAT2,
+ * location: WebGLUniformLocation
+ * },
+ * "uniform2Name[0]":
+ * {
+ * name: "uniform2Name[0]",
+ * size: 4,
+ * type: gl.FLOAT,
+ * location: WebGLUniformLocation
+ * },
+ * }
+ *
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {WebGLProgram} The program to query for uniforms.
+ * @return the map.
+ */
+var getUniformMap = function(gl, program) {
+ return getActiveMap(gl, program, {
+ param: "ACTIVE_UNIFORMS",
+ activeFn: "getActiveUniform",
+ locFn: "getUniformLocation"
+ });
+};
+
+var basePath;
+var getResourcePath = function() {
+ if (!basePath) {
+ var expectedBase = "js/webgl-test-utils.js";
+ var scripts = document.getElementsByTagName('script');
+ for (var script, i = 0; script = scripts[i]; i++) {
+ var src = script.src;
+ var l = src.length;
+ if (src.substr(l - expectedBase.length) == expectedBase) {
+ basePath = src.substr(0, l - expectedBase.length);
+ }
+ }
+ }
+ return basePath + "resources/";
+};
+
+var loadStandardVertexShader = function(gl) {
+ return loadShaderFromFile(
+ gl, getResourcePath() + "vertexShader.vert", gl.VERTEX_SHADER);
+};
+var loadStandardVertexShaderAsync = function(gl, callback) {
+ loadShaderFromFileAsync(gl, getResourcePath() + "vertexShader.vert", gl.VERTEX_SHADER, undefined, undefined, undefined, callback);
+};
+
+var loadStandardFragmentShader = function(gl) {
+ return loadShaderFromFile(
+ gl, getResourcePath() + "fragmentShader.frag", gl.FRAGMENT_SHADER);
+};
+var loadStandardFragmentShaderAsync = function(gl, callback) {
+ loadShaderFromFileAsync(gl, getResourcePath() + "fragmentShader.frag", gl.FRAGMENT_SHADER, undefined, undefined, undefined, callback);
+};
+
+var loadUniformBlockProgram = function(gl) {
+ var program = gl.createProgram();
+ gl.attachShader(program, loadUniformBlockVertexShader(gl));
+ gl.attachShader(program, loadUniformBlockFragmentShader(gl));
+ gl.bindAttribLocation(program, 0, "a_vertex");
+ gl.bindAttribLocation(program, 1, "a_normal");
+ linkProgram(gl, program);
+ return program;
+};
+
+var loadUniformBlockVertexShader = function(gl) {
+ return loadShaderFromFile(
+ gl, getResourcePath() + "uniformBlockShader.vert", gl.VERTEX_SHADER);
+};
+
+var loadUniformBlockFragmentShader = function(gl) {
+ return loadShaderFromFile(
+ gl, getResourcePath() + "uniformBlockShader.frag", gl.FRAGMENT_SHADER);
+};
+
+/**
+ * Loads an image asynchronously.
+ * @param {string} url URL of image to load.
+ * @param {!function(!Element): void} callback Function to call
+ * with loaded image.
+ */
+var loadImageAsync = function(url, callback) {
+ var img = document.createElement('img');
+ img.onload = function() {
+ callback(img);
+ };
+ img.src = url;
+};
+
+/**
+ * Loads an array of images.
+ * @param {!Array.<string>} urls URLs of images to load.
+ * @param {!function(!{string, img}): void} callback Callback
+ * that gets passed map of urls to img tags.
+ */
+var loadImagesAsync = function(urls, callback) {
+ var count = 1;
+ var images = { };
+ function countDown() {
+ --count;
+ if (count == 0) {
+ log("loadImagesAsync: all images loaded");
+ callback(images);
+ }
+ }
+ function imageLoaded(url) {
+ return function(img) {
+ images[url] = img;
+ log("loadImagesAsync: loaded " + url);
+ countDown();
+ }
+ }
+ for (var ii = 0; ii < urls.length; ++ii) {
+ ++count;
+ loadImageAsync(urls[ii], imageLoaded(urls[ii]));
+ }
+ countDown();
+};
+
+/**
+ * Returns a map of key=value values from url.
+ * @return {!Object.<string, number>} map of keys to values.
+ */
+var getUrlArguments = function() {
+ var args = {};
+ try {
+ var s = window.location.href;
+ var q = s.indexOf("?");
+ var e = s.indexOf("#");
+ if (e < 0) {
+ e = s.length;
+ }
+ var query = s.substring(q + 1, e);
+ var pairs = query.split("&");
+ for (var ii = 0; ii < pairs.length; ++ii) {
+ var keyValue = pairs[ii].split("=");
+ var key = keyValue[0];
+ var value = decodeURIComponent(keyValue[1]);
+ args[key] = value;
+ }
+ } catch (e) {
+ throw "could not parse url";
+ }
+ return args;
+};
+
+/**
+ * Makes an image from a src.
+ * @param {string} src Image source URL.
+ * @param {function()} onload Callback to call when the image has finised loading.
+ * @param {function()} onerror Callback to call when an error occurs.
+ * @return {!Image} The created image.
+ */
+var makeImage = function(src, onload, onerror) {
+ var img = document.createElement('img');
+ if (onload) {
+ img.onload = onload;
+ }
+ if (onerror) {
+ img.onerror = onerror;
+ } else {
+ img.onerror = function() {
+ log("WARNING: creating image failed; src: " + this.src);
+ };
+ }
+ if (src) {
+ img.src = src;
+ }
+ return img;
+}
+
+/**
+ * Makes an image element from a canvas.
+ * @param {!HTMLCanvas} canvas Canvas to make image from.
+ * @param {function()} onload Callback to call when the image has finised loading.
+ * @param {string} imageFormat Image format to be passed to toDataUrl().
+ * @return {!Image} The created image.
+ */
+var makeImageFromCanvas = function(canvas, onload, imageFormat) {
+ return makeImage(canvas.toDataURL(imageFormat), onload);
+};
+
+/**
+ * Makes a video element from a src.
+ * @param {string} src Video source URL.
+ * @param {function()} onerror Callback to call when an error occurs.
+ * @return {!Video} The created video.
+ */
+var makeVideo = function(src, onerror) {
+ var vid = document.createElement('video');
+ if (onerror) {
+ vid.onerror = onerror;
+ } else {
+ vid.onerror = function() {
+ log("WARNING: creating video failed; src: " + this.src);
+ };
+ }
+ if (src) {
+ vid.src = src;
+ }
+ return vid;
+}
+
+/**
+ * Inserts an image with a caption into 'element'.
+ * @param {!HTMLElement} element Element to append image to.
+ * @param {string} caption caption to associate with image.
+ * @param {!Image} img image to insert.
+ */
+var insertImage = function(element, caption, img) {
+ var div = document.createElement("div");
+ var label = document.createElement("div");
+ label.appendChild(document.createTextNode(caption));
+ div.appendChild(label);
+ div.appendChild(img);
+ element.appendChild(div);
+};
+
+/**
+ * Inserts a 'label' that when clicked expands to the pre formatted text
+ * supplied by 'source'.
+ * @param {!HTMLElement} element element to append label to.
+ * @param {string} label label for anchor.
+ * @param {string} source preformatted text to expand to.
+ * @param {string} opt_url URL of source. If provided a link to the source file
+ * will also be added.
+ */
+var addShaderSource = function(element, label, source, opt_url) {
+ var div = document.createElement("div");
+ var s = document.createElement("pre");
+ s.className = "shader-source";
+ s.style.display = "none";
+ var ol = document.createElement("ol");
+ //s.appendChild(document.createTextNode(source));
+ var lines = source.split("\n");
+ for (var ii = 0; ii < lines.length; ++ii) {
+ var line = lines[ii];
+ var li = document.createElement("li");
+ li.appendChild(document.createTextNode(line));
+ ol.appendChild(li);
+ }
+ s.appendChild(ol);
+ var l = document.createElement("a");
+ l.href = "show-shader-source";
+ l.appendChild(document.createTextNode(label));
+ l.addEventListener('click', function(event) {
+ if (event.preventDefault) {
+ event.preventDefault();
+ }
+ s.style.display = (s.style.display == 'none') ? 'block' : 'none';
+ return false;
+ }, false);
+ div.appendChild(l);
+ if (opt_url) {
+ var u = document.createElement("a");
+ u.href = opt_url;
+ div.appendChild(document.createTextNode(" "));
+ u.appendChild(document.createTextNode("(" + opt_url + ")"));
+ div.appendChild(u);
+ }
+ div.appendChild(s);
+ element.appendChild(div);
+};
+
+/**
+ * Inserts labels that when clicked expand to show the original source of the
+ * shader and also translated source of the shader, if that is available.
+ * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!HTMLElement} element element to append label to.
+ * @param {string} label label for anchor.
+ * @param {WebGLShader} shader Shader to show the sources for.
+ * @param {string} shaderSource Original shader source.
+ * @param {string} opt_url URL of source. If provided a link to the source file
+ * will also be added.
+ */
+var addShaderSources = function(
+ gl, element, label, shader, shaderSource, opt_url) {
+ addShaderSource(element, label, shaderSource, opt_url);
+
+ var debugShaders = gl.getExtension('WEBGL_debug_shaders');
+ if (debugShaders && shader) {
+ var translatedSource = debugShaders.getTranslatedShaderSource(shader);
+ if (translatedSource != '') {
+ addShaderSource(element, label + ' translated for driver', translatedSource);
+ }
+ }
+};
+
+/**
+ * Sends shader information to the server to be dumped into text files
+ * when tests are run from within the test-runner harness.
+ * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} url URL of current.
+ * @param {string} passMsg Test description.
+ * @param {object} vInfo Object containing vertex shader information.
+ * @param {object} fInfo Object containing fragment shader information.
+ */
+var dumpShadersInfo = function(gl, url, passMsg, vInfo, fInfo) {
+ var shaderInfo = {};
+ shaderInfo.url = url;
+ shaderInfo.testDescription = passMsg;
+ shaderInfo.vLabel = vInfo.label;
+ shaderInfo.vShouldCompile = vInfo.shaderSuccess;
+ shaderInfo.vSource = vInfo.source;
+ shaderInfo.fLabel = fInfo.label;
+ shaderInfo.fShouldCompile = fInfo.shaderSuccess;
+ shaderInfo.fSource = fInfo.source;
+ shaderInfo.vTranslatedSource = null;
+ shaderInfo.fTranslatedSource = null;
+ var debugShaders = gl.getExtension('WEBGL_debug_shaders');
+ if (debugShaders) {
+ if (vInfo.shader)
+ shaderInfo.vTranslatedSource = debugShaders.getTranslatedShaderSource(vInfo.shader);
+ if (fInfo.shader)
+ shaderInfo.fTranslatedSource = debugShaders.getTranslatedShaderSource(fInfo.shader);
+ }
+
+ var dumpShaderInfoRequest = new XMLHttpRequest();
+ dumpShaderInfoRequest.open('POST', "/dumpShaderInfo", true);
+ dumpShaderInfoRequest.setRequestHeader("Content-Type", "text/plain");
+ dumpShaderInfoRequest.send(JSON.stringify(shaderInfo));
+};
+
+// Add your prefix here.
+var browserPrefixes = [
+ "",
+ "MOZ_",
+ "OP_",
+ "WEBKIT_"
+];
+
+/**
+ * Given an extension name like WEBGL_compressed_texture_s3tc
+ * returns the name of the supported version extension, like
+ * WEBKIT_WEBGL_compressed_teture_s3tc
+ * @param {string} name Name of extension to look for.
+ * @return {string} name of extension found or undefined if not
+ * found.
+ */
+var getSupportedExtensionWithKnownPrefixes = function(gl, name) {
+ var supported = gl.getSupportedExtensions();
+ for (var ii = 0; ii < browserPrefixes.length; ++ii) {
+ var prefixedName = browserPrefixes[ii] + name;
+ if (supported.indexOf(prefixedName) >= 0) {
+ return prefixedName;
+ }
+ }
+};
+
+/**
+ * Given an extension name like WEBGL_compressed_texture_s3tc
+ * returns the supported version extension, like
+ * WEBKIT_WEBGL_compressed_teture_s3tc
+ * @param {string} name Name of extension to look for.
+ * @return {WebGLExtension} The extension or undefined if not
+ * found.
+ */
+var getExtensionWithKnownPrefixes = function(gl, name) {
+ for (var ii = 0; ii < browserPrefixes.length; ++ii) {
+ var prefixedName = browserPrefixes[ii] + name;
+ var ext = gl.getExtension(prefixedName);
+ if (ext) {
+ return ext;
+ }
+ }
+};
+
+/**
+ * Returns possible prefixed versions of an extension's name.
+ * @param {string} name Name of extension. May already include a prefix.
+ * @return {Array.<string>} Variations of the extension name with known
+ * browser prefixes.
+ */
+var getExtensionPrefixedNames = function(name) {
+ var unprefix = function(name) {
+ for (var ii = 0; ii < browserPrefixes.length; ++ii) {
+ if (browserPrefixes[ii].length > 0 &&
+ name.substring(0, browserPrefixes[ii].length).toLowerCase() ===
+ browserPrefixes[ii].toLowerCase()) {
+ return name.substring(browserPrefixes[ii].length);
+ }
+ }
+ return name;
+ }
+
+ var unprefixed = unprefix(name);
+
+ var variations = [];
+ for (var ii = 0; ii < browserPrefixes.length; ++ii) {
+ variations.push(browserPrefixes[ii] + unprefixed);
+ }
+
+ return variations;
+};
+
+var replaceRE = /\$\((\w+)\)/g;
+
+/**
+ * Replaces strings with property values.
+ * Given a string like "hello $(first) $(last)" and an object
+ * like {first:"John", last:"Smith"} will return
+ * "hello John Smith".
+ * @param {string} str String to do replacements in.
+ * @param {...} 1 or more objects containing properties.
+ */
+var replaceParams = function(str) {
+ var args = arguments;
+ return str.replace(replaceRE, function(str, p1, offset, s) {
+ for (var ii = 1; ii < args.length; ++ii) {
+ if (args[ii][p1] !== undefined) {
+ return args[ii][p1];
+ }
+ }
+ throw "unknown string param '" + p1 + "'";
+ });
+};
+
+var upperCaseFirstLetter = function(str) {
+ return str.substring(0, 1).toUpperCase() + str.substring(1);
+};
+
+/**
+ * Gets a prefixed property. For example,
+ *
+ * var fn = getPrefixedProperty(
+ * window,
+ * "requestAnimationFrame");
+ *
+ * Will return either:
+ * "window.requestAnimationFrame",
+ * "window.oRequestAnimationFrame",
+ * "window.msRequestAnimationFrame",
+ * "window.mozRequestAnimationFrame",
+ * "window.webKitRequestAnimationFrame",
+ * undefined
+ *
+ * the non-prefixed function is tried first.
+ */
+var propertyPrefixes = ["", "moz", "ms", "o", "webkit"];
+var getPrefixedProperty = function(obj, propertyName) {
+ for (var ii = 0; ii < propertyPrefixes.length; ++ii) {
+ var prefix = propertyPrefixes[ii];
+ var name = prefix + propertyName;
+ log(name);
+ var property = obj[name];
+ if (property) {
+ return property;
+ }
+ if (ii == 0) {
+ propertyName = upperCaseFirstLetter(propertyName);
+ }
+ }
+ return undefined;
+};
+
+var _requestAnimFrame;
+
+/**
+ * Provides requestAnimationFrame in a cross browser way.
+ */
+var requestAnimFrame = function(callback) {
+ if (!_requestAnimFrame) {
+ _requestAnimFrame = getPrefixedProperty(window, "requestAnimationFrame") ||
+ function(callback, element) {
+ return window.setTimeout(callback, 1000 / 70);
+ };
+ }
+ _requestAnimFrame.call(window, callback);
+};
+
+var _cancelAnimFrame;
+
+/**
+ * Provides cancelAnimationFrame in a cross browser way.
+ */
+var cancelAnimFrame = function(request) {
+ if (!_cancelAnimFrame) {
+ _cancelAnimFrame = getPrefixedProperty(window, "cancelAnimationFrame") ||
+ window.clearTimeout;
+ }
+ _cancelAnimFrame.call(window, request);
+};
+
+/**
+ * Provides requestFullScreen in a cross browser way.
+ */
+var requestFullScreen = function(element) {
+ var fn = getPrefixedProperty(element, "requestFullScreen");
+ if (fn) {
+ fn.call(element);
+ }
+};
+
+/**
+ * Provides cancelFullScreen in a cross browser way.
+ */
+var cancelFullScreen = function() {
+ var fn = getPrefixedProperty(document, "cancelFullScreen");
+ if (fn) {
+ fn.call(document);
+ }
+};
+
+var fullScreenStateName;
+(function() {
+ var fullScreenStateNames = [
+ "isFullScreen",
+ "fullScreen"
+ ];
+ for (var ii = 0; ii < fullScreenStateNames.length; ++ii) {
+ var propertyName = fullScreenStateNames[ii];
+ for (var jj = 0; jj < propertyPrefixes.length; ++jj) {
+ var prefix = propertyPrefixes[jj];
+ if (prefix.length) {
+ propertyName = upperCaseFirstLetter(propertyName);
+ fullScreenStateName = prefix + propertyName;
+ if (document[fullScreenStateName] !== undefined) {
+ return;
+ }
+ }
+ }
+ fullScreenStateName = undefined;
+ }
+}());
+
+/**
+ * @return {boolean} True if fullscreen mode is active.
+ */
+var getFullScreenState = function() {
+ log("fullscreenstatename:" + fullScreenStateName);
+ log(document[fullScreenStateName]);
+ return document[fullScreenStateName];
+};
+
+/**
+ * @param {!HTMLElement} element The element to go fullscreen.
+ * @param {!function(boolean)} callback A function that will be called
+ * when entering/exiting fullscreen. It is passed true if
+ * entering fullscreen, false if exiting.
+ */
+var onFullScreenChange = function(element, callback) {
+ propertyPrefixes.forEach(function(prefix) {
+ var eventName = prefix + "fullscreenchange";
+ log("addevent: " + eventName);
+ document.addEventListener(eventName, function(event) {
+ log("event: " + eventName);
+ callback(getFullScreenState());
+ });
+ });
+};
+
+/**
+ * @param {!string} buttonId The id of the button that will toggle fullscreen
+ * mode.
+ * @param {!string} fullscreenId The id of the element to go fullscreen.
+ * @param {!function(boolean)} callback A function that will be called
+ * when entering/exiting fullscreen. It is passed true if
+ * entering fullscreen, false if exiting.
+ * @return {boolean} True if fullscreen mode is supported.
+ */
+var setupFullscreen = function(buttonId, fullscreenId, callback) {
+ if (!fullScreenStateName) {
+ return false;
+ }
+
+ var fullscreenElement = document.getElementById(fullscreenId);
+ onFullScreenChange(fullscreenElement, callback);
+
+ var toggleFullScreen = function(event) {
+ if (getFullScreenState()) {
+ cancelFullScreen(fullscreenElement);
+ } else {
+ requestFullScreen(fullscreenElement);
+ }
+ event.preventDefault();
+ return false;
+ };
+
+ var buttonElement = document.getElementById(buttonId);
+ buttonElement.addEventListener('click', toggleFullScreen);
+
+ return true;
+};
+
+/**
+ * Waits for the browser to composite the web page.
+ * @param {function()} callback A function to call after compositing has taken
+ * place.
+ */
+var waitForComposite = function(callback) {
+ var frames = 5;
+ var countDown = function() {
+ if (frames == 0) {
+ // TODO(kbr): unify with js-test-pre.js and enable these with
+ // verbose logging.
+ // log("waitForComposite: callback");
+ callback();
+ } else {
+ // log("waitForComposite: countdown(" + frames + ")");
+ --frames;
+ requestAnimFrame.call(window, countDown);
+ }
+ };
+ countDown();
+};
+
+/**
+ * Runs an array of functions, yielding to the browser between each step.
+ * If you want to know when all the steps are finished add a last step.
+ * @param {!Array.<function(): void>} steps Array of functions.
+ */
+var runSteps = function(steps) {
+ if (!steps.length) {
+ return;
+ }
+
+ // copy steps so they can't be modifed.
+ var stepsToRun = steps.slice();
+ var currentStep = 0;
+ var runNextStep = function() {
+ stepsToRun[currentStep++]();
+ if (currentStep < stepsToRun.length) {
+ setTimeout(runNextStep, 1);
+ }
+ };
+ runNextStep();
+};
+
+/**
+ * Starts playing a video and waits for it to be consumable.
+ * @param {!HTMLVideoElement} video An HTML5 Video element.
+ * @param {!function(!HTMLVideoElement): void} callback Function to call when
+ * video is ready.
+ */
+var startPlayingAndWaitForVideo = function(video, callback) {
+ var gotPlaying = false;
+ var gotTimeUpdate = false;
+
+ var maybeCallCallback = function() {
+ if (gotPlaying && gotTimeUpdate && callback) {
+ callback(video);
+ callback = undefined;
+ video.removeEventListener('playing', playingListener, true);
+ video.removeEventListener('timeupdate', timeupdateListener, true);
+ }
+ };
+
+ var playingListener = function() {
+ gotPlaying = true;
+ maybeCallCallback();
+ };
+
+ var timeupdateListener = function() {
+ // Checking to make sure the current time has advanced beyond
+ // the start time seems to be a reliable heuristic that the
+ // video element has data that can be consumed.
+ if (video.currentTime > 0.0) {
+ gotTimeUpdate = true;
+ maybeCallCallback();
+ }
+ };
+
+ video.addEventListener('playing', playingListener, true);
+ video.addEventListener('timeupdate', timeupdateListener, true);
+ video.loop = true;
+ video.play();
+};
+
+var getHost = function(url) {
+ url = url.replace("\\", "/");
+ var pos = url.indexOf("://");
+ if (pos >= 0) {
+ url = url.substr(pos + 3);
+ }
+ var parts = url.split('/');
+ return parts[0];
+}
+
+// This function returns the last 2 words of the domain of a URL
+// This is probably not the correct check but it will do for now.
+var getBaseDomain = function(host) {
+ var parts = host.split(":");
+ var hostname = parts[0];
+ var port = parts[1] || "80";
+ parts = hostname.split(".");
+ if(parts.length < 2)
+ return hostname + ":" + port;
+ var tld = parts[parts.length-1];
+ var domain = parts[parts.length-2];
+ return domain + "." + tld + ":" + port;
+}
+
+var runningOnLocalhost = function() {
+ return window.location.hostname.indexOf("localhost") != -1 ||
+ window.location.hostname.indexOf("127.0.0.1") != -1;
+}
+
+var getLocalCrossOrigin = function() {
+ var domain;
+ if (window.location.host.indexOf("localhost") != -1) {
+ domain = "127.0.0.1";
+ } else {
+ domain = "localhost";
+ }
+
+ var port = window.location.port || "80";
+ return window.location.protocol + "//" + domain + ":" + port
+}
+
+var getRelativePath = function(path) {
+ var relparts = window.location.pathname.split("/");
+ relparts.pop(); // Pop off filename
+ var pathparts = path.split("/");
+
+ var i;
+ for (i = 0; i < pathparts.length; ++i) {
+ switch (pathparts[i]) {
+ case "": break;
+ case ".": break;
+ case "..":
+ relparts.pop();
+ break;
+ default:
+ relparts.push(pathparts[i]);
+ break;
+ }
+ }
+
+ return relparts.join("/");
+}
+
+var setupImageForCrossOriginTest = function(img, imgUrl, localUrl, callback) {
+ window.addEventListener("load", function() {
+ if (typeof(img) == "string")
+ img = document.querySelector(img);
+ if (!img)
+ img = new Image();
+
+ img.addEventListener("load", callback, false);
+ img.addEventListener("error", callback, false);
+
+ if (runningOnLocalhost())
+ img.src = getLocalCrossOrigin() + getRelativePath(localUrl);
+ else
+ img.src = getUrlOptions().imgUrl || imgUrl;
+ }, false);
+}
+
+/**
+ * Convert sRGB color to linear color.
+ * @param {!Array.<number>} color The color to be converted.
+ * The array has 4 elements, for example [R, G, B, A].
+ * where each element is in the range 0 to 255.
+ * @return {!Array.<number>} color The color to be converted.
+ * The array has 4 elements, for example [R, G, B, A].
+ * where each element is in the range 0 to 255.
+ */
+var sRGBToLinear = function(color) {
+ return [sRGBChannelToLinear(color[0]),
+ sRGBChannelToLinear(color[1]),
+ sRGBChannelToLinear(color[2]),
+ color[3]]
+}
+
+/**
+ * Convert linear color to sRGB color.
+ * @param {!Array.<number>} color The color to be converted.
+ * The array has 4 elements, for example [R, G, B, A].
+ * where each element is in the range 0 to 255.
+ * @return {!Array.<number>} color The color to be converted.
+ * The array has 4 elements, for example [R, G, B, A].
+ * where each element is in the range 0 to 255.
+ */
+var linearToSRGB = function(color) {
+ return [linearChannelToSRGB(color[0]),
+ linearChannelToSRGB(color[1]),
+ linearChannelToSRGB(color[2]),
+ color[3]]
+}
+
+function sRGBChannelToLinear(value) {
+ value = value / 255;
+ if (value <= 0.04045)
+ value = value / 12.92;
+ else
+ value = Math.pow((value + 0.055) / 1.055, 2.4);
+ return Math.trunc(value * 255 + 0.5);
+}
+
+function linearChannelToSRGB(value) {
+ value = value / 255;
+ if (value <= 0.0) {
+ value = 0.0;
+ } else if (value < 0.0031308) {
+ value = value * 12.92;
+ } else if (value < 1) {
+ value = Math.pow(value, 0.41666) * 1.055 - 0.055;
+ } else {
+ value = 1.0;
+ }
+ return Math.trunc(value * 255 + 0.5);
+}
+var API = {
+ addShaderSource: addShaderSource,
+ addShaderSources: addShaderSources,
+ cancelAnimFrame: cancelAnimFrame,
+ create3DContext: create3DContext,
+ GLErrorException: GLErrorException,
+ create3DContextWithWrapperThatThrowsOnGLError: create3DContextWithWrapperThatThrowsOnGLError,
+ checkAreaInAndOut: checkAreaInAndOut,
+ checkCanvas: checkCanvas,
+ checkCanvasRect: checkCanvasRect,
+ checkCanvasRectColor: checkCanvasRectColor,
+ checkCanvasRects: checkCanvasRects,
+ checkFloatBuffer: checkFloatBuffer,
+ checkTextureSize: checkTextureSize,
+ clipToRange: clipToRange,
+ createColoredTexture: createColoredTexture,
+ createProgram: createProgram,
+ clearAndDrawUnitQuad: clearAndDrawUnitQuad,
+ clearAndDrawIndexedQuad: clearAndDrawIndexedQuad,
+ drawUnitQuad: drawUnitQuad,
+ drawIndexedQuad: drawIndexedQuad,
+ drawUByteColorQuad: drawUByteColorQuad,
+ drawFloatColorQuad: drawFloatColorQuad,
+ dumpShadersInfo: dumpShadersInfo,
+ endsWith: endsWith,
+ failIfGLError: failIfGLError,
+ fillTexture: fillTexture,
+ getBytesPerComponent: getBytesPerComponent,
+ getDefault3DContextVersion: getDefault3DContextVersion,
+ getExtensionPrefixedNames: getExtensionPrefixedNames,
+ getExtensionWithKnownPrefixes: getExtensionWithKnownPrefixes,
+ getFileListAsync: getFileListAsync,
+ getLastError: getLastError,
+ getPrefixedProperty: getPrefixedProperty,
+ getScript: getScript,
+ getSupportedExtensionWithKnownPrefixes: getSupportedExtensionWithKnownPrefixes,
+ getTypedArrayElementsPerPixel: getTypedArrayElementsPerPixel,
+ getUrlArguments: getUrlArguments,
+ getUrlOptions: getUrlOptions,
+ getAttribMap: getAttribMap,
+ getUniformMap: getUniformMap,
+ glEnumToString: glEnumToString,
+ glErrorShouldBe: glErrorShouldBe,
+ glTypeToTypedArrayType: glTypeToTypedArrayType,
+ hasAttributeCaseInsensitive: hasAttributeCaseInsensitive,
+ insertImage: insertImage,
+ loadImageAsync: loadImageAsync,
+ loadImagesAsync: loadImagesAsync,
+ loadProgram: loadProgram,
+ loadProgramFromFile: loadProgramFromFile,
+ loadProgramFromScript: loadProgramFromScript,
+ loadProgramFromScriptExpectError: loadProgramFromScriptExpectError,
+ loadShader: loadShader,
+ loadShaderFromFile: loadShaderFromFile,
+ loadShaderFromScript: loadShaderFromScript,
+ loadStandardProgram: loadStandardProgram,
+ loadStandardProgramAsync: loadStandardProgramAsync,
+ loadStandardVertexShader: loadStandardVertexShader,
+ loadStandardVertexShaderAsync: loadStandardVertexShaderAsync,
+ loadStandardFragmentShader: loadStandardFragmentShader,
+ loadStandardFragmentShaderAsync: loadStandardFragmentShaderAsync,
+ loadUniformBlockProgram: loadUniformBlockProgram,
+ loadUniformBlockVertexShader: loadUniformBlockVertexShader,
+ loadUniformBlockFragmentShader: loadUniformBlockFragmentShader,
+ loadTextFileAsync: loadTextFileAsync,
+ loadTexture: loadTexture,
+ log: log,
+ loggingOff: loggingOff,
+ makeCheckRect: makeCheckRect,
+ makeImage: makeImage,
+ makeImageFromCanvas: makeImageFromCanvas,
+ makeVideo: makeVideo,
+ error: error,
+ shallowCopyObject: shallowCopyObject,
+ setDefault3DContextVersion: setDefault3DContextVersion,
+ setupColorQuad: setupColorQuad,
+ setupProgram: setupProgram,
+ setupTransformFeedbackProgram: setupTransformFeedbackProgram,
+ setupQuad: setupQuad,
+ setupIndexedQuad: setupIndexedQuad,
+ setupIndexedQuadWithOptions: setupIndexedQuadWithOptions,
+ setupSimpleColorProgram: setupSimpleColorProgram,
+ setupSimpleTextureProgram: setupSimpleTextureProgram,
+ setupSimpleCubeMapTextureProgram: setupSimpleCubeMapTextureProgram,
+ setupSimpleVertexColorProgram: setupSimpleVertexColorProgram,
+ setupNoTexCoordTextureProgram: setupNoTexCoordTextureProgram,
+ setupTexturedQuad: setupTexturedQuad,
+ setupTexturedQuadWithTexCoords: setupTexturedQuadWithTexCoords,
+ setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
+ setupUnitQuad: setupUnitQuad,
+ setupUnitQuadWithTexCoords: setupUnitQuadWithTexCoords,
+ setFloatDrawColor: setFloatDrawColor,
+ setUByteDrawColor: setUByteDrawColor,
+ startPlayingAndWaitForVideo: startPlayingAndWaitForVideo,
+ startsWith: startsWith,
+ shouldGenerateGLError: shouldGenerateGLError,
+ readFile: readFile,
+ readFileList: readFileList,
+ replaceParams: replaceParams,
+ requestAnimFrame: requestAnimFrame,
+ runSteps: runSteps,
+ waitForComposite: waitForComposite,
+
+ // fullscreen api
+ setupFullscreen: setupFullscreen,
+
+ // sRGB converter api
+ sRGBToLinear: sRGBToLinear,
+ linearToSRGB: linearToSRGB,
+
+ getHost: getHost,
+ getBaseDomain: getBaseDomain,
+ runningOnLocalhost: runningOnLocalhost,
+ getLocalCrossOrigin: getLocalCrossOrigin,
+ getRelativePath: getRelativePath,
+ setupImageForCrossOriginTest: setupImageForCrossOriginTest,
+
+ none: false
+};
+
+Object.defineProperties(API, {
+ noTexCoordTextureVertexShader: { value: noTexCoordTextureVertexShader, writable: false },
+ simpleTextureVertexShader: { value: simpleTextureVertexShader, writable: false },
+ simpleColorFragmentShader: { value: simpleColorFragmentShader, writable: false },
+ simpleVertexShader: { value: simpleVertexShader, writable: false },
+ simpleTextureFragmentShader: { value: simpleTextureFragmentShader, writable: false },
+ simpleCubeMapTextureFragmentShader: { value: simpleCubeMapTextureFragmentShader, writable: false },
+ simpleVertexColorFragmentShader: { value: simpleVertexColorFragmentShader, writable: false },
+ simpleVertexColorVertexShader: { value: simpleVertexColorVertexShader, writable: false }
+});
+
+return API;
+
+}());